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

时间:2009-11-10 21:51:32

标签: java c++ class struct java-native-interface

我目前正在项目中使用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当前返回一个UnsatisfiedLinkError。有什么问题?

3 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分: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访问该对象(好吧,我添加一些引用计数的东西,但这非常先进)。希望有所帮助。

技术

答案 2 :(得分: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返回值?