I'm writing a C API wrapper for my own C++ library. I want to use the C-API with JNA in Java.
For each class in the C++ library I wrapped the constructors in C function calls, returning a handle. With this handle I can call C functions, which are wrapping the object's member functions (casting the handle to it's class and calling its member function). This works fine.
To simplify the use of my API in Java, I wrote classes for all C++ classes. These Java classes only contain a JNA-Pointer (storing my objects handle) and the public member function of the C++ call. Each member function of the Java class calls the C function which is wrapping the C++ object's member function.
Now I'm facing a Problem:
When a C++ member function returns a reference to another C++ object, then my C-API returns the pointer. But how do I construct my Java objects out of this pointer? Is it legit to create a new Java Object and set its pointer value to the returned value. Although in Java are now 2 Objects, which holding the same pointer value.
Or should I have a List in Java, keeping track of all C++ objects, so I can get the returned reference from C++ out of this list.
When does the the Garbage Collector remove the JNA-Pointer objects from heap? And when gets my C++ object deleted?
(Some code to specify my answer)
In my C-API I have the following Function to create an Object
int C_API_createFoo(void **handle) {
try {
*handle = reinterpret_cast<void*>(new Foo());
return SUCCESS;
} catch (std::exception &err) {
std::cout << err.what() << std::endl;
return ERROR;
}
}
In Java/JNA I load my C-lib and call the function with the following code:
public Pointer createFoo(){
PointerByReference pRef = new PointerByReference();
int eC = MyClib.INSTANCE.C_API_createFoo(pRef);
CHECK(eC);
return pRef.getValue();
}
Where Foo is:
public class Foo{
private Pointer handle;
public Foo(){
this.handle = createFoo();
}
public Foo(Pointer handle){
this.handle = handle;
}
}
So now the class Foo stores the Object handle and can be used as a normal Java Object.
But suggest I have a C++ class for example FooWorker which has a member variable of Type Foo and has a getter Function for Foo:
int C_API_FooWorker_getFoo(void* FooWorkerHandle, void** fooHandle) {
try {
FooWorker* fW= reinterpret_cast<FooWorker*>(FooWorkerHandle);
Foo *foo = fW.getFoo();
*fooHandle = reinterpret_cast<void*>(foo);
return SUCCESS;
} catch (std::exception &err) {
std::cout << err.what() << std::endl;
return ERROR;
}
}
Which is mapped in JNA like:
public Foo FooWorker_getFoo(Pointer fooWorkerHandle){
PointerByReference pRef = new PointerByReference();
int eC = MyClib.INSTANCE.C_API_FooWorker_getFoo(fooWorkerHandle, pRef);
CHECK(eC);
return new Foo(pRef.getValue());
}
So when I call the function FooWorker_getFoo(Pointer fooWorkerHandle) multiple times with the same value for fooWorkerHandle, than I will get multiple Java Objects of type Foo, but all containing the same value for their handle (i.e. the same C++ object reference).
Question
My Question is now: Is this save or will it cause any pain? And will all these Foo Objects (and in the end the one and only C++ Object, all the handles pointing to) be collected by the garbage collection?