Java很久,第一次使用C++.
我正在编写一个包装现有C++ API的Java类,看起来像这样:
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);
}
Run Code Online (Sandbox Code Playgroud)
我们将指向本机C++对象的指针填充到handle字段中.
问题是C++库没有给我一个指针,它给了我一个unique_ptr<Foo>.所以这必须被移到堆上openFile()(因此它不会超出范围),然后被销毁closeFile().
我无法让这个工作,我不确定我是否正确地做到了.在C++中正确执行此操作的最简单/最简洁的方法是什么?
这是我目前正在做的事情:
// 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
}
Run Code Online (Sandbox Code Playgroud)
它是否正确?如果是这样,可以简化吗?
在任何情况下,现在程序都崩溃了closeFile(),但我不知道它是否崩溃,因为我做错了或者我正在使用的库中有一些错误(它相对较新且有错误).
感谢任何"指针".
它可以简化.
既然你必须与Java的生命周期管理集成,那么对unique_ptr你没有任何好处.你也可以T直接管理对象的生命周期,而不是它的包装器(当然也不是FooHolder包装器的unique_ptr包装器T- 这太多包装).
只要打电话release()就unique_ptr<T>得到T*一个需要delete,当你用它做-d.