I'm trying to call a Java function from C++ with a custom class type argument. The issue is that the Java function gets garbage values when called from C++ (code shown below). If I use the argument of any other data type (String, float, int) the same function printClassVar
works correctly.
This is the Java code
/*Filename: CallbacksExample.java*/
public class CallbacksExample {
static {
System.loadLibrary("myjni");
}
public static void main(String[] args) {
new CallbacksExample().callback();
}
public native void callback();
public static void printClassVar(Person person)
{
System.out.println("Got callback from C++: " + person.age );
}
}
/*Filename: Person.java*/
public class Person {
public int age;
public Person() {
this.age = 20;
}
public int value() {
return age;
}
}
And here is the JNI code
/*Filename: CallbacksExample.cpp*/
#include <iostream>
#include <jni.h>
#include "CallbacksExample.h"
using namespace std;
class Person
{
int age;
public:
Person()
{
age = 5;
}
int value()
{
return age;
}
};
JNIEXPORT void JNICALL
Java_CallbacksExample_callback(JNIEnv *env, jobject jthis)
{
jclass thisClass = env->GetObjectClass(jthis);
Person _per;
Person* class_ptr = &_per;
std::cout << class_ptr->value() << std::endl;
jmethodID printClassVar = env->GetStaticMethodID(thisClass, "printClassVar", "(LPerson;)V");
if (NULL == printClassVar)
return;
env->CallVoidMethod(jthis, printClassVar, &class_ptr);
}
The above code returns
Got callback from C++: 1679598160 (Or any garbage signed int value)
Here is the proper way to call a Java function with class type argument in C++
/*Filename: CallbacksExample.java*/
public class CallbacksExample {
static {
System.loadLibrary("myjni");
}
public static void main(String[] args) {
new CallbacksExample().callback();
}
public native void callback();
public static void printClassVar(Person person)
{
System.out.println("Got callback from C++: " + person.age );
}
}
/*Filename: Person.java*/
public class Person {
public int age;
public Person() {
this.age = 20;
}
public void set(int x)
{
age = x;
}
public int value() {
return age;
}
}
/*Filename: CallbacksExample.cpp*/
#include <iostream>
#include <jni.h>
#include "CallbacksExample.h"
JNIEXPORT void JNICALL
Java_CallbacksExample_callback(JNIEnv *env, jobject jthis)
{
jclass thisClass = env->GetObjectClass(jthis);
jclass personClass = env->FindClass("Person");
jmethodID class_constructor = env->GetMethodID(personClass, "<init>", "()V"); // no parameters
jobject personObj = env->NewObject(personClass, class_constructor);
auto personMethod = env->GetMethodID(personClass, "set", "(I)V");
env->CallVoidMethod(personObj, personMethod, 15);
jmethodID printClassVar = env->GetStaticMethodID(thisClass, "printClassVar", "(LPerson;)V");
if (NULL == printClassVar)
return;
env->CallVoidMethod(jthis, printClassVar, personObj);
}