Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the foxiz-core domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/posttrau/public_html/mdtWordpress/wp-includes/functions.php on line 6114
Calling Java methods from C++ - My Day To-Do
In one of my projects, I had the need to call a Java function from a C++ class and somewhat surprisingly it was more complicated than I initially expected it to be. Arguably there are more resources on how to call C++ functions from a Java class then the other way around. Also one needs to ensure that the documentation refers to calling Java methods from C++ instead of C, as there differences in the function calls. Hence based on my experience here’s the solution that I came up with.

Requirements

I wanted a Java class to perform a certain task and return an array of double (primitive type). I would then invoke this Java method from my C++ class and use the values of that double array.
A sample of my Java class
public class Test{ 
    public[] double array; 
    public int size; 
    public double[] getArray() { 
        array = new double[]{1.2,3.2,1.2}; return array; 
    } 
} 

Hurdles and initial mistakes

Initially what I was trying was to invoke the method using the code below which was causing a segmentation fault i.e. segfault (a term we all know and love)
void getArrayFromJava(JNIEnv* env)
{
    jmethodID method;
    jclass testClass = env->FindClass("test");
    method = env->GetMethodID(testClass,"getArray","()Ljava/lang/Object");
    //below is the point in code where the segmentation fault in the jvm occured
    jdoubleArray r = (jdoubleArray)env->CallObjectMethod(testClass,method,NULL);
    return r;
}
At first I thought it was because I was calling an object method directly without instantiating the object, however even when I did change the getArrayFromJava method to a static method, the same segfault occurred.

Calling Java methods from C++

So what did I do? Well, I declare the double array as well as the size(arraySize) of the array as class variables and that are set when instantiating the Java class i.e. via values passed in the constructor.
the java code being called
class Test{
    public double[] array = null;
    public int arraySize;
    public String str;
    public Test(String value,int val)
    {
        str = value;
        setArray(val);
        arraySize = 3;
    }
    public void setArray(int val)
    {
        double []db = new double[]{val,val,1.4};
        this.array = db;
    }
}
Below is the C++ code that invokes the uses the Java class Test. To keep this post brief and to focus on the main objective of this post, I will not going into details of creating a pointer to the JNIEnv. You could get that info from one of the links in theReferences used section of this post or those of you reading this post, think that this post is incomplete without it, please let me know and I will see what I can do to add that info here.

Get updates?

void getArrayFromJava(JNIEnv* env)
{
    jclass testClass;
    jobject testObj;
    jmethodID constructor;
    const char* utfChars;
    testClass = env->FindClass("Test");//get the class
    //get the constructor for the java class by using <init>
    constructor = env->GetMethodID(testClass,"<init>","(Ljava/lang/String;I)V");
    jstring stringArgs = env->NewStringUTF("nTest sample");
    jint intParam = 1;
    testObj = env->NewObject(testClass,constructor,stringArgs,intParam);//instantiate a class object

    //get the array field from the object
    jobject tArr = env->GetObjectField(testObj,env->GetFieldID(testClass,"array","[D"));

    //get the array size field from the object
    jint arraySize = (jint)env->GetIntField(testObj,env->GetFieldID(testClass,"arraySize","I"););

    jdoubleArray *arr = reinterpret_cast<jdoubleArray*>(&tArr);
    //now we have a pointer to the array and a size which tells us of the number of elements

    double* data = env->GetDoubleArrayElements(*arr,NULL);
    /*accessing a pointer to a double array is now simple and can be done using the information in 'data' and array size' */
}

References used

http://java.sun.com/docs/books/jni/html/objtypes.html#4013 http://www.codeproject.com/Articles/22881/How-to-Call-Java-Functions-from-C-Using-JNI http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html#run

Conclusion

If you find any of my posts useful and want to support me, you can buy me a coffee 🙂 https://www.buymeacoffee.com/bhumansoni Or you can  buying or even try one of my apps on the App Store. 
https://mydaytodo.com/apps/

Get updates?

Or have a look at some useful Javascript tutorials below 
https://mydaytodo.com/category/javascript/
Categories: C++Java

0 Comments

Leave a Reply

Avatar placeholder
Verified by MonsterInsights