JNI, C++ object instantiation

So my next task is to create a java gui using a C++ library.
The library is pretty simple. There is one main class with a few supporting classes. The supporting classes are basically just structs which hold variables.
The first thing to be done is create a Java class similar to the main C++ class. This is called a peer class. The methods in the java class are native functions whose implementations will be done using the Java Native Interface (JNI).
In the java class constructor, a jni call to create the C++ class will need to be made. The java class will also need to override the finalize function in which it will have a jni call to delete the C++ class.
The java class also needs to contain a variable which will be used to contain the pointer to the C++ class.
Now my first problem: How do I implement the JNI function which creates the C++ class? If anyone knows the answer, feel free to leave me a comment.
According to this link, a reinterpret cast is involved.

C++ class:

#include “CPPObject.h”
#include

CppObject::CppObject(int aFoo) {
foo = aFoo;
}

void CppObject::printFoo() {
printf (“Value of foo is: %in”, foo);
}

Java peer class:

public class CppObjectPeer {
static {
System.loadLibrary(“cppobjects”);
}
protected long ptr;
public CppObjectPeer(int aFoo) {
this.ptr = createCppObject(aFoo); //create object in native code
}
public void printFoo() {
printFoo(this.ptr); //print from native code
}
//native methods
private final native long createCppObject(int aFoo);
private native void printFoo(long ptr);
}

Jni implementations:

JNIEXPORT jlong JNICALL Java_CppObjectPeer_createCppObject
(JNIEnv *env, jobject obj, jint fooValue) {
CppObject *cppObj = new CppObject(fooValue);
return reinterpret_cast(cppObj);
}

JNIEXPORT void JNICALL Java_CppObjectPeer_printFoo
(JNIEnv *env, jobject obj, jlong ptr) {
CppObject *cppObj = reinterpret_cast(ptr);
cppObj->printFoo();
}

Well, it looks simple enough. Just not sure why the book: Essential Jni: Java Native Interface (Essential Java), by Rob Gordon doesn’t use this technique. Is this a new technique?

The book uses a Registry class and a hash code function to store the pointer to the C++ object. This method seems like a lot of work for what I need. As an alternative, he suggests using get/setCID functions which call get/setLongField functions. The set functions requires an int val be passed in and I don’t understand where the val comes from. I guess for now I’m going to try the reinterpret_cast method.
Stay tuned for how it works out.


Comments

  1. how did it work?

  2. It worked out great, except in place of the reinterpret_cast call, I cast the return value to a (jlong) in the jni Java_CppObjectPeer_createCppObject function.
    When the jlong value is passed into the jni Java_CppObjectPeer_printFoo function,
    I cast to the object type instead of using the reinterpret_cast:
    CppObject *cppObj = (CppObject*) (ptr);

  3. Hello,

    I was looking for some tutorial for communicating between C++ class functions and Java, and I found your blog. Thank you for sharing what you found and how you made it working. It was quite useful.

    I tried to work on the code that you posted, but am getting error:

    In function Java_CppObjectPeer_printFoo':
    CppObjectPeer.cpp:(.text+0x73): undefined reference to `CPPObject::printFoo()'
    collect2: ld returned 1 exit status

    The following is the implementation of the functions, like you suggested:
    #include "CppObjectPeer.h"
    #include "CPPObject.h"
    #include

    JNIEXPORT jlong JNICALL Java_CppObjectPeer_createCppObject (JNIEnv *env, jobject obj, jint fooValue) {
    CPPObject *cppObj = new CPPObject(fooValue);
    return (jlong)(cppObj);
    }

    JNIEXPORT void JNICALL Java_CppObjectPeer_printFoo (JNIEnv *env, jobject obj, jlong ptr){
    CPPObject *cppObj = (CPPObject*)(ptr);
    cppObj->printFoo();
    }

    Did you get any such error?

    Thank you.

Leave a Reply