Long time Java, first time C++.
I'm writing a Java class that wraps an existing C++ API and looks something like this:
public class Foo implements Closeable {
private long handle;
public Foo(File file) {
this.handle = Foo.openFile(file.toString());
}
// other methods go here...
public void close() {
Foo.closeFile(this.handle);
this.handle = 0;
}
private static native long openFile(String file);
private static native void closeFile(long handle);
}
We will stuff the pointer to the native C++ object into the handle
field.
The problem is that the C++ library doesn't give me a pointer, it gives me a unique_ptr<Foo>
. So this has to be moved onto the heap in openFile()
(so it doesn't go out of scope), and then destroyed in closeFile()
.
I'm having trouble getting this to work, and am not sure if I'm doing it properly. What is the simplest/cleanest way to do this correctly in C++?
Here's what I'm currently doing:
// This holds a unique_ptr<T>, typically on the heap, until no longer needed
template <class T>
class PointerHolder {
public:
PointerHolder(unique_ptr<T> ptr) {
this->ptr = std::move(ptr);
}
T * get() const {
return this->ptr.get();
}
private:
unique_ptr<T> ptr;
};
// Holder for a Foo
typedef PointerHolder<Foo> FooHolder;
jlong JNICALL
Java_Foo_openFile(JNIEnv *jenv, jclass jcls, jstring file)
{
...
// Get smart pointer to native object from provided C++ library
unique_ptr<Foo> ptr = ...
// Save pointer on the heap until closeFile() is invoked sometime later
const FooHolder *const holder = new FooHolder(std::move(ptr));
// Return pointer encoded as a Java long
return reinterpret_cast<jlong>(holder);
}
void JNICALL
Java_Foo_closeFile(JNIEnv *jenv, jclass jcls, jlong handle)
{
// Delete pointer holder, and by extension, storage object
delete reinterpret_cast<FooHolder *>(handle); // CRASH HERE
}
Is this correct? If so, can it be simplified?
In any case, right now the program is crashing in closeFile()
, but I can't tell if it's crashing because I'm doing something wrong or there is some bug in the library I'm using (it's relatively new and buggy).
Thanks for any "pointers".