Returning a C++ class to Java via JNI

2019-03-11 04:20发布

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++.

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.

In C++ I have:

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).

On the Java end, I do a simple call to this method,

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?

3条回答
对你真心纯属浪费
2楼-- · 2019-03-11 05:08

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.

(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)
String aString = "valuesoftheobject";
MyObject myObject(aString);

MyObject would have a constructor which takes a string. I believe the solution is simple and effective.

查看更多
叛逆
3楼-- · 2019-03-11 05:16

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:

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.

Your UnsatisfiedLinkError may be the extra character in your function name as written above, or perhaps it can't handle the MyObject return value?

查看更多
We Are One
4楼-- · 2019-03-11 05:24

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.

I use it extensively in Xuggler. To see an example, if you download the Xuggler source code there is a C++ object here:

csrc/com/xuggle/xuggler/IStreamCoder.h

I define a SWIG interface file here:

csrc/com/xuggle/xuggler/IStreamCoder.i

And when run through Swig it generates a Java object (which is stored here)

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.

Art

查看更多
登录 后发表回答