I have just started at a new job. Here we are new to using JNI ( for bridging C++ / Java ). I am new to JNI so please forgive my noobness :)
In our (win32) Java app we are loading a C++ DLL. On the Java side we have several instances of "SomeJClass" each of these instances needs access to corresponding instance of "SomeCClass" on the DLL side. The DLL exposes entry-points such as GlobalDoSomethingInC(). Here I must call the instance method of Doer::DoSomethingInC(). So I need a smooth way to map the respective this-pointers. I also need to do the same mapping when a DLL thread discovers something interesting that it needs to notify the corresponding Java-instance of.
I can think of several solutions, but I do not like them too much. My question is, is there a better way than this ?
1 Java calls C:GetNewInstance(). This returns an int that is actually a pointer to the new C instance. Java stores it in m_myCInstance. Then Java calls GlobalDoSomethingInC(), and 1a
// DLL global
void GlobalDoSomethingInC()
{
// retrive this pointer
//calling back to Java:
jobj tmpJ = NewGlobalRef( env, obj );
Doer* myDoer = <reinterpret_cast>( Doer )tmpJ->GetMyCInstance();
myDoer->DoSomething();
DeleteGlobalRef( env, tmpJ );
// Arrrrgh
}
1b or:
// for **every call** that Java adds a parameter,
//which is the stored int:m_myCInstance, and
Doer* myDoer = <reinterpret_cast>( Doer )instanceParam->DoSomethingInC();
// Can we do better that this?
2 For calling from C to Java, things look, maybe, better
In the constructor C calls back into Java and stores
the Java instance reference
in a member variable. m_myJInstance.
In all subsequent calls m_myJInstance can be used to call back Java.
In the destructor we need to call DeleteGlobalRef( env, m_myJInstance );
Not too bad I suppose. But it really safe to store the jobject reference. I mean: What happens when the GC moves the object around?
3 Our present solution does "work". But it belongs on rather on http://www.codinghorror.com/blog/ :)
Thanx