Using JNI can we pass custom data types from Java to C (or vice versa)? I see a mapping of primitive datatypes to types in C however not too sure if we can send across our own data types (e.g. Send across or return an Employee object or something!).
Asked
Active
Viewed 4.2k times
34
-
You can use [JNA](https://github.com/twall/jna/) to easily pass structures around. JNA allows you to write your binding completely in Java code. :-) – C. K. Young Mar 23 '10 at 23:52
-
You can. If you want to make Java/C translation easier, check out [Swig](http://www.swig.org/), which allows you to translate [between Java and C/C++ structures](http://www.swig.org/Doc1.3/Java.html) in a straightforward fashion.. – Brian Agnew Mar 23 '10 at 23:26
-
https://www.baeldung.com/jni#2-using-objects-and-calling-java-methods-from-native-code – Leponzo Jul 05 '21 at 18:41
1 Answers
75
If you're going to be doing this with a lot of objects, something like Swig would be best. You could use jobject type to pass around custom objects. The syntax isn't nice, perhaps there is a better way to write this.
Example Employee object:
public class Employee {
private int age;
public Employee(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
Call this code from some client:
public class Client {
public Client() {
Employee emp = new Employee(32);
System.out.println("Pass employee to C and get age back: "+getAgeC(emp));
Employee emp2 = createWithAge(23);
System.out.println("Get employee object from C: "+emp2.getAge());
}
public native int getAgeC(Employee emp);
public native Employee createWithAge(int age);
}
You could have JNI functions like this for passing an employee object from Java to C, as a jobject method argument:
JNIEXPORT jint JNICALL Java_Client_getAgeC(JNIEnv *env, jobject callingObject, jobject employeeObject) {
jclass employeeClass = (*env)->GetObjectClass(env, employeeObject);
jmethodID midGetAge = (*env)->GetMethodID(env, employeeClass, "getAge", "()I");
int age = (*env)->CallIntMethod(env, employeeObject, midGetAge);
return age;
}
Passing an employee object back from C to Java as a jobject, you could use:
JNIEXPORT jobject JNICALL Java_Client_createWithAge(JNIEnv *env, jobject callingObject, jint age) {
jclass employeeClass = (*env)->FindClass(env,"LEmployee;");
jmethodID midConstructor = (*env)->GetMethodID(env, employeeClass, "<init>", "(I)V");
jobject employeeObject = (*env)->NewObject(env, employeeClass, midConstructor, age);
return employeeObject;
}
-
3I have problems with "LEmployee;" part I tried with "com.pak1.Employee" and with "Lcom.pak.Employee;" but no result, any ideas ? – Lukap Oct 09 '13 at 10:27
-
2@Lukap: if your class is com.pak.Employee then the signature of the class will be "Lcom/pak/Employee;" – nautilusvn Jul 06 '14 at 10:26
-
1@mafioso you can create an object of class "Ljava/lang/string;". Commenting for completeness, doubt you actually still need this... – Nepho Nov 03 '17 at 12:27
-
The `jclass proc_jclass = env->FindClass(“Lcom/my/class/JavaClass”);` method needs to be called at the FIRST LINE of your `JNI` function or else you may experience `ClassNotFoundExceptions`. Also, this did not work for me with the semi-colon in the class path. Once I removed the semi-colon from the classpath string, it worked. This is a Great answer! – Sakiboy Jan 28 '19 at 20:24
-
1