通过 JNI 将 C++ 类返回给 Java
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1711490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Returning a C++ class to Java via JNI
提问by tomzx
I'm currently using both C++ and Java in a project and I'd like to be able to send an object which is contained in C++ to my Java interface in order to modify it via a GUI and then send the modification back in C++.
我目前在一个项目中同时使用 C++ 和 Java,我希望能够将包含在 C++ 中的对象发送到我的 Java 界面,以便通过 GUI 修改它,然后将修改发送回 C++。
So far I've been returning either nothing, an int or a boolean to Java via the JNI interface. This time I have to send an object through the interface. I have made similar class definition available both in C++ and in Java. I'd like to know how I'd go about creating the object so that I can use it in Java.
到目前为止,我一直没有通过 JNI 接口向 Java 返回任何内容,一个 int 或一个布尔值。这次我要通过接口发送一个对象。我在 C++ 和 Java 中都提供了类似的类定义。我想知道如何创建对象以便我可以在 Java 中使用它。
In C++ I have:
在 C++ 中,我有:
JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number);
This function would get called by Java in order to get the object from the C++ side (the object is contained in a singleton, easily accessible).
Java 会调用此函数以从 C++ 端获取对象(该对象包含在单例中,易于访问)。
On the Java end, I do a simple call to this method,
在Java端,我对这个方法做了一个简单的调用,
MyObject anObject = C_getMyObject(3);
which should return me the newly created object.
这应该返回我新创建的对象。
Java currently returns me a UnsatisfiedLinkError when I do the actual call. What is wrong?
当我进行实际调用时,Java 当前返回一个 UnsatisfiedLinkError。怎么了?
采纳答案by tomzx
Here's the solution I opted to use:
这是我选择使用的解决方案:
First, I would create a similar object in Java. Then, from C++ I would instanciate it and pass it all the values.
首先,我会在 Java 中创建一个类似的对象。然后,从 C++ 我会实例化它并将所有值传递给它。
(C++)
clazz = env->FindClass("java/lang/Integer");
jmethodID method = env->GetMethodID(clazz, "<init>", "(I)V");
return env->NewObject(clazz, method, (jint)anInteger);
But then I realised this wasn't very portable and was a bit too complicated.
但后来我意识到这不是很便携,而且有点太复杂了。
Instead, I decided to return a string that Java would parse and use to initialize the object on its side.
相反,我决定返回一个字符串,Java 将解析并用它来初始化它一侧的对象。
(JAVA)
String aString = "valuesoftheobject";
MyObject myObject(aString);
MyObject would have a constructor which takes a string. I believe the solution is simple and effective.
MyObject 将有一个接受字符串的构造函数。我相信解决方案既简单又有效。
回答by Michael Brewer-Davis
If your MyObject
class is defined in C++, you're not going to be able access its methods in Java. I'd try to define a Java wrapper class around your C object:
如果您的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);
If you can extrapolate a C api instead, you might try JNA.
如果您可以外推 C api,则可以尝试JNA。
Your UnsatisfiedLinkError may be the extra character in your function name as written above, or perhaps it can't handle the MyObject
return value?
你的 UnsatisfiedLinkError 可能是你上面写的函数名中的额外字符,或者它可能无法处理MyObject
返回值?
回答by Art Clarke
Another tool you should look at is SWIG. SWIG is a great tool for generate wrappers in other languages (such as Java, Python or C#) for existing C/C++ objects. It will generate automatic Java wrappers around C/C++ objects, and do all the heavy JNI lifting for you.
您应该查看的另一个工具是SWIG。SWIG 是一个很好的工具,可以用其他语言(例如 Java、Python 或 C#)为现有的 C/C++ 对象生成包装器。它将围绕 C/C++ 对象生成自动 Java 包装器,并为您完成所有繁重的 JNI 工作。
I use it extensively in Xuggler. To see an example, if you download the Xuggler source code there is a C++ object here:
我在Xuggler 中广泛使用它。举个例子,如果你下载 Xuggler 源代码,这里有一个 C++ 对象:
csrc/com/xuggle/xuggler/IStreamCoder.h
I define a SWIG interface file here:
我在这里定义了一个 SWIG 接口文件:
csrc/com/xuggle/xuggler/IStreamCoder.i
And when run through Swig it generates a Java object (which is stored here)
当通过 Swig 运行时,它会生成一个 Java 对象(存储在这里)
generate/java/com/xuggle/xuggler/IStreamCoder.java
We can then access that object from Java easily (well, I add some ref counting stuff, but that's pretty advanced). Hope that helps.
然后我们可以轻松地从 Java 访问该对象(好吧,我添加了一些引用计数的东西,但这非常先进)。希望有帮助。
Art
艺术