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

17

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

到目前为止,我已经通过JNI接口向Java返回了空,int或boolean。这一次我必须通过接口发送一个对象。我已经在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在实际调用时返回了UnsatisfiedLinkError错误信息。出了什么问题?

3个回答

12

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

首先,我会在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应该有一个接受字符串参数的构造函数。我相信解决方案是简单而有效的。


5
另一个你应该看看的工具是SWIG。SWIG是一个很好的工具,可以为现有的C/C++对象生成其他语言(如Java、Python或C#)的包装器。它会自动生成C/C++对象的Java包装器,并为你完成所有繁琐的JNI工作。
我在Xuggler中广泛使用它。要查看一个示例,如果你下载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访问该对象(我添加了一些引用计数的东西,但那是相当高级的)。希望这有所帮助。
艺术

4
如果您的MyObject类是在C++中定义的,那么您将无法在Java中访问其方法。我建议尝试在C对象周围定义一个Java包装器类:
Java:
public C_Object() {
   handle = createHandle();
}

private native long createHandle(); // or whatever pointer/handle type?

public void doStuff() {
   _doStuff(handle);
}

private native void _doStuff(long handle);

如果您可以推断出C API,可以尝试使用JNA
您的UnsatisfiedLinkError可能是由于函数名称中的额外字符,或者它无法处理MyObject返回值所导致的?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接