Skip to main content

Calling Java methods from C++

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

My Solution

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 the References 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.
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







Comments

Popular posts from this blog

Upload to AWS S3 from Java API

In this post, you will see code samples for how to upload a file to AWS S3 bucket from a Java Spring Boot app. The code you will see here is from one of my open-source repositories on Github, called document-sharing. Problem Let’s say you are building a document sharing app where you allow your users to upload the file to a public cloud solution. Now, let’s say you are building the API for your app with Spring Boot and you are using AWS S3 as your public cloud solution. How would you do that? This blog post contains the code that can help you achieve that. Read more below,  Upload to AWS S3 bucket from Java Spring Boot app - My Day To-Do (mydaytodo.com)

Addressing app review rejections for auto-renewing subscription in-app purchase (iOS)

The ability to know what the weather is like while planning your day is a feature of  My Day To-Do  Pro and as of the last update it’s also a part of the  Lite version . Unlike the Pro version it’s an auto-renewing subscription based  in-app purchase (IAP)  in the Lite version. What means is that when a user purchases it, the user only pays for the subscription duration after which the user will be automatically charged for the next period. Adding an  auto-renewing  subscription based IAP proved to be somewhat challenging in terms of the app store review i.e. the app update was rejected by the App Review team thrice because of missing information about the IAP. Therefore in this post I will share my experiences and knowledge of adding auto-renewing IAP in hopes to save someone else the time that I had to spend on this problem. In-App purchase This year I started adding IAPs to My Day To-Do Lite which lead to learning about different types of IAP...

Getting started with iOS programming using Swift (Part 1)

I have not been too fond of Objective-C, which was the primary reason for me to stay away from making iOS apps till now. So what changed? Well Apple has done something very interesting recently and that is the introduction of a new programming language i.e. Swift. Swift is awesome, it almost feels like Python, C++ and Objective-C had a baby with some of their good parts in them. So I have been getting to know Swift and it is an awesome language to program in. What I am going to share with this and a series of blog posts are solutions to some problems that i have encounter while i am trying to finish my first iOS app. The one hurdle that I have encountered while getting started on developing an iOS app is that a majority of the solutions for iOS specific problems provide solutions to them using Objective-C. Which is fair, because Swift has not been around for that long. Anyway let us get started with a few basics, A few basics I would highly recommend having a read of this book...