tags:

views:

348

answers:

3

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

+1  A: 

You can. If you want to make Java/C translation easier, check out Swig, which allows you to translate between Java and C/C++ structures in a straightforward fashion..

Brian Agnew
A: 

You can use JNA to easily pass structures around. JNA allows you to write your binding completely in Java code. :-)

Chris Jester-Young
+2  A: 

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 midGetName = (*env)->GetMethodID(env, employeeClass, "getAge", "()I");
    int age =  (*env)->CallIntMethod(env, employeeObject, midGetName);
    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;
}
Stew