c++ - JNI 与 C++ 对象实例

标签 c++ java-native-interface instance

我刚开始一份新工作。在这里,我们刚开始使用 JNI(用于桥接 C++/Java)。我是 JNI 的新手所以请原谅我的菜鸟:)

在我们的 (win32) Java 应用程序中,我们正在加载一个 C++ DLL。在 Java 端,我们有多个“SomeJClass”实例,每个实例都需要访问 DLL 端相应的“SomeCClass”实例。 DLL 公开入口点,例如 GlobalDoSomethingInC()。这里我必须调用Doer::DoSomethingInC()的实例方法。所以我需要一种平滑的方法来映射各自的 this-pointers。 当 DLL 线程发现一些有趣的东西需要通知相应的 Java 实例时,我也需要做同样的映射。

我能想到几种解决方案,但我不太喜欢它们。我的问题是,还有比这更好的方法吗?

1 Java 调用 C:GetNewInstance()。这将返回一个 int,它实际上是指向新 C 实例的指针。 Java 将其存储在 m_myCInstance 中。然后 Java 调用 GlobalDoSomethingInC(),并且 1a

// DLL global
void GlobalDoSomethingInC()
{
    // retrive this pointer
    //calling back to Java:  
    jobj tmpJ = NewGlobalRef( env, obj );
    Doer* myDoer = <reinterpret_cast>( Doer )tmpJ->GetMyCInstance();
    myDoer->DoSomething();
    DeleteGlobalRef( env, tmpJ );
    // Arrrrgh
}

1b 或:

    // for **every call** that Java adds a parameter, 
    //which is the stored int:m_myCInstance, and
    Doer* myDoer = <reinterpret_cast>( Doer )instanceParam->DoSomethingInC();
    // Can we do better that this?

2 对于从 C 到 Java 的调用,事情看起来可能更好

In the constructor C calls back into Java and stores
the Java instance reference 
    in a member variable. m_myJInstance.
    In all subsequent calls m_myJInstance can be used to call back Java.
    In the destructor we need to call DeleteGlobalRef( env, m_myJInstance );

我想还不错。但是存储作业对象引用确实很安全。 我的意思是:当 GC 移动对象时会发生什么?

3 我们目前的解决方案确实“有效”。但它属于 http://www.codinghorror.com/blog/ :)

谢谢

最佳答案

通常这在某种程度上取决于您的环境。我只用过 KNI,它比 JNI 还要原始。我认为有点丑陋是不可避免的,因为您在两个系统之间混合内存跟踪,其中只有一个有 GC。

一般来说,我发现最好将 C 代码中的所有调用包装在函数中,以处理令人讨厌的转换,我认为这是不可避免的。 (顺便说一句,我在这里使用 C 来表示非 Java 代码)

在C 端,Java 对象的移动绝对是​​一个潜在的问题。这将取决于您的平台,但我希望只要您在库中,就不会发生 Java GC,因此您的对象是稳定的。您需要确定这一点。另一方面,如果不是这样,那你就完蛋了。假设是这种情况,您希望对公开给 JNI 的函数执行相同的解除引用/强制转换操作,以便您可以愉快地在所有调用的函数中使用普通 C 对象。

真正丑陋的地方是,如果您可以让对象超出任何一侧的范围,那么任何一侧都可能持有对您的对象的引用。这里我们在 Java 端使用终结器,在 C 端使用析构函数。它并不漂亮,但我认为这是不可避免的。

所以,简短的回答,它会有点丑陋,隔离两种语言之间的界面周围的丑陋,这样对于大部分工作,无论是哪种语言,您都不必担心这些事情。

还值得为存在于此接口(interface)上的对象创建一个基类,因为在这里您还可以隔离一些丑陋之处。

关于c++ - JNI 与 C++ 对象实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/796845/

相关文章:

java - 如何以正确的方式创建一个具有多种用途的对象?

c++ - C++中的libxml2,如何设置编码

java - C++/JNI - 如何访问在 JAVA (Android NDK) 中的 .h 中声明的枚举

java - 包装 C++ 对象的最佳 JNI 模式?

java - 将 Java 嵌入到 C++ 应用程序中?

javascript - 为什么从构造函数返回时未定义原型(prototype)?

c++ - oaidl.h(319) : error C2057: expected constant expression

c++ - 防止实例化未使用的默认函数参数

java - 在 Maven 测试中获取 native JNI 文件 (lwjgl)

javafx - 如何再次启动外部 JavaFX 程序?即使 JavaFX 程序以 Platform.Exit 结束,Launch 也会阻止这种情况发生