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