Search code examples
javac++dlljava-native-interface

How to pass a classobject to a jni native method


I want to create a DLL, which takes a java class object as parameter. Let's say I create some native methods, which takes a Human.class instance as parameter. How could I write the C++ implementation of it, in order to access the human object? Is it even possible?

(Please consider, that I have no experience with C++ at all.)

I already did some research, as it looks like I need to access a pointer from C++. This confused me a little bit, as at this point I don't understand how C++ should know about the human object and it's properties.

e.g.

JNI.class

public class FourthJNI {

    public static native int returnAgeOfHuman(Human abc);
    public static void main(String[] args) {

        Human testHuman = new Human("ABC", 23, "M");
        /* Call to shared library */
        int ageOfHuman = FourthJNI.returnAgeOfHuman(testHuman);
        System.out.println(testHuman.toString());
        System.out.println("Age of Human: " + ageOfHuman);
    }

}

human.class

import java.io.Serializable;

public class Human implements Serializable{


    /**
     * 
     */
    private static final long serialVersionUID = -5591105366105425395L;
    private String name;
    private int age;
    private String sex;

    public Human(String name, int age, String sex) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
    }


    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }


    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((sex == null) ? 0 : sex.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Human other = (Human) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (sex == null) {
            if (other.sex != null)
                return false;
        } else if (!sex.equals(other.sex))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "Human [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }

}

generated header file

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class FourthJNI */

#ifndef _Included_FourthJNI
#define _Included_FourthJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     FourthJNI
 * Method:    returnAgeOfHuman
 * Signature: (LHuman;)I
 */
JNIEXPORT jint JNICALL Java_FourthJNI_returnAgeOfHuman
  (JNIEnv *, jclass, jobject);

#ifdef __cplusplus
}
#endif
#endif

How should my C++ implementation look like?


Solution

  • You have to deconstruct Java class inside C++ code. You have to use JNI methods and access data inside object - field by field.

    Basically, you will have to make few calls of following shape

    /* Get int field 
         Take a look here, we are passing char* with 
         field descriptor - e.g. "I" => int 
    */
    
    jfieldID fidInt = (*env)->GetFieldID (env, cls, "iVal", "I");
    jint iVal = (*env)->GetIntField (env, objarg, fidInt);
    printf ("iVal: %d\n", iVal);
    

    It's pointless to give you full sample here, it would take quite lots of space and time to put it here. Just follow the manual.

    You can find description here: http://jnicookbook.owsiak.org/recipe-No-020/

    And you can find source code here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo020