在堆上存储 unique_ptr 的最简单方法是什么?
What is the simplest way to stash a unique_ptr on the heap?
很久Java,第一次C++。
我正在写一个 Java class 包装现有的 C++ API 并且看起来像这样:
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);
}
我们会将指向本机 C++ 对象的指针填充到 handle
字段中。
问题是 C++ 库没有给我一个指针,它给了我一个 unique_ptr<Foo>
。所以这必须在 openFile()
中移动到堆上(因此它不会超出范围),然后在 closeFile()
.
中销毁
我在让它工作时遇到了问题,我不确定我是否做对了。在 C++ 中正确执行此操作的 simplest/cleanest 方法是什么?
这是我目前正在做的事情:
// 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
}
这是正确的吗?如果可以,可以简化一下吗?
无论如何,现在程序在 closeFile()
中崩溃,但我无法判断它是否崩溃是因为我做错了什么或者我正在使用的库中存在一些错误(它相对较新且有错误)。
感谢任何"pointers"。
可以简化。
由于您必须与 Java 的生命周期管理集成,因此 unique_ptr
对您没有任何帮助。您还不如直接管理 T
对象的生命周期,而不是它的包装器(当然不是 FooHolder
包装器 unique_ptr
包装器 T
- - 包装太多了)。
只需在 unique_ptr<T>
上调用 release()
即可获得 T*
,完成后需要 delete
-d。
很久Java,第一次C++。
我正在写一个 Java class 包装现有的 C++ API 并且看起来像这样:
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);
}
我们会将指向本机 C++ 对象的指针填充到 handle
字段中。
问题是 C++ 库没有给我一个指针,它给了我一个 unique_ptr<Foo>
。所以这必须在 openFile()
中移动到堆上(因此它不会超出范围),然后在 closeFile()
.
我在让它工作时遇到了问题,我不确定我是否做对了。在 C++ 中正确执行此操作的 simplest/cleanest 方法是什么?
这是我目前正在做的事情:
// 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
}
这是正确的吗?如果可以,可以简化一下吗?
无论如何,现在程序在 closeFile()
中崩溃,但我无法判断它是否崩溃是因为我做错了什么或者我正在使用的库中存在一些错误(它相对较新且有错误)。
感谢任何"pointers"。
可以简化。
由于您必须与 Java 的生命周期管理集成,因此 unique_ptr
对您没有任何帮助。您还不如直接管理 T
对象的生命周期,而不是它的包装器(当然不是 FooHolder
包装器 unique_ptr
包装器 T
- - 包装太多了)。
只需在 unique_ptr<T>
上调用 release()
即可获得 T*
,完成后需要 delete
-d。