【发布时间】:2021-02-18 06:31:39
【问题描述】:
我正在为我自己的 C++ 库编写 C API 包装器。我想在 Java 中将 C-API 与 JNA 一起使用。
对于 C++ 库中的每个类,我将构造函数包装在 C 函数调用中,并返回一个句柄。使用这个句柄,我可以调用 C 函数,这些函数包装了对象的成员函数(将句柄转换为它的类并调用它的成员函数)。 这很好用。
为了简化我在 Java 中 API 的使用,我为所有 C++ 类编写了类。这些 Java 类仅包含一个 JNA 指针(存储我的对象句柄)和 C++ 调用的公共成员函数。 Java 类的每个成员函数都调用了 C 函数,该 C 函数包装了 C++ 对象的成员函数。
现在我面临一个问题:
当 C++ 成员函数返回对另一个 C++ 对象的引用时,我的 C-API 将返回指针。但是如何用这个指针构造我的 Java 对象呢?创建一个新的 Java 对象并将其指针值设置为返回值是否合法。尽管在 Java 中现在有 2 个对象,它们持有相同的指针值。
或者我应该在 Java 中有一个 List,跟踪所有 C++ 对象,这样我就可以从这个列表中获取 C++ 返回的引用。
垃圾收集器何时从堆中删除 JNA-Pointer 对象?什么时候删除我的 C++ 对象?
(一些代码来指定我的答案)
在我的 C-API 中,我有以下函数来创建对象
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;
}
}
在 Java/JNA 中,我加载我的 C-lib 并使用以下代码调用该函数:
public Pointer createFoo(){
PointerByReference pRef = new PointerByReference();
int eC = MyClib.INSTANCE.C_API_createFoo(pRef);
CHECK(eC);
return pRef.getValue();
}
Foo 在哪里:
public class Foo{
private Pointer handle;
public Foo(){
this.handle = createFoo();
}
public Foo(Pointer handle){
this.handle = handle;
}
}
所以现在Foo 类存储了对象句柄,可以用作普通的Java 对象。
但建议我有一个 C++ 类,例如 FooWorker,它有一个类型为 Foo 的成员变量,并有一个用于 Foo 的 getter 函数:
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;
}
}
在 JNA 中映射如下:
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());
}
所以当我多次调用函数FooWorker_getFoo(Pointer fooWorkerHandle) 并使用相同的fooWorkerHandle 值时,我将获得多个Foo 类型的Java 对象,但它们的句柄都包含相同的值(即相同的C++对象引用)。
问题
我现在的问题是:这是保存还是会引起任何痛苦?并且所有这些 Foo 对象(最后是唯一的 C++ 对象,所有指向的句柄)都会被垃圾收集器收集吗?
【问题讨论】:
-
通过具体的代码示例,我可以回答更多,但因为这是您的问题太宽泛,并且为高质量的答案提出了太多问题。
-
感谢您的回答。我编辑了我的问题并添加了一些代码。也许这让我的广泛问题稍微简化了一点。