通过 JNI 将C++类返回到 Java

2022-09-03 01:47:57

我目前在项目中同时使用C++和Java,我希望能够将C++中包含的对象发送到我的Java接口,以便通过GUI对其进行修改,然后在C++中发送回修改。

到目前为止,我一直没有通过JNI接口向Java返回任何内容,int或布尔值。这次我必须通过界面发送一个对象。我已经在C++和Java中提供了类似的类定义。我想知道我将如何创建对象,以便我可以在Java中使用它。

在C++我有:

JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number);

Java会调用这个函数,以便从C++端获取对象(对象包含在单例中,易于访问)。

在Java端,我对这个方法做了一个简单的调用,

MyObject anObject = C_getMyObject(3);

这应该返回我新创建的对象。

Java目前在我执行实际调用时返回一个不满意的LinkError。怎么了?


答案 1

以下是我选择使用的解决方案:

首先,我会在Java中创建一个类似的对象。然后,从C++开始,我将实例化它并传递所有值。

(C++)
clazz = env->FindClass("java/lang/Integer");
jmethodID method = env->GetMethodID(clazz, "<init>", "(I)V");
return env->NewObject(clazz, method, (jint)anInteger);

但后来我意识到这不是很便携,而且有点太复杂了。

相反,我决定返回一个字符串,Java将解析该字符串并用于在其一侧初始化对象。

(JAVA)
String aString = "valuesoftheobject";
MyObject myObject(aString);

MyObject 将有一个构造函数,它接受一个字符串。我相信解决方案简单有效。


答案 2

您应该查看的另一个工具是SWIG。SWIG是一个很好的工具,用于为现有的C / C++对象生成其他语言(如Java,Python或C#)的包装器。它将围绕C / C++对象生成自动Java包装器,并为您完成所有繁重的JNI提升。

我在Xugler中广泛使用它。要查看示例,如果您下载 Xuggler 源代码,则此处有一个C++对象:

csrc/com/xuggle/xuggler/IStreamCoder.h

我在这里定义了一个SWIG接口文件:

csrc/com/xuggle/xuggler/IStreamCoder.i

当通过Swig运行时,它会生成一个Java对象(存储在此处)

generate/java/com/xuggle/xuggler/IStreamCoder.java

然后,我们可以轻松地从Java访问该对象(好吧,我添加了一些引用计数的东西,但这非常高级)。希望有所帮助。

艺术