Returning an array of complex object is not straight forward in JNI, Here I will explain an example doing it.
JAVA part.
StudentRecord.java
package com.test;
public class StudentRecord {
public String name;
public int rollNumber;
public String departement;
public float totalMark;
boolean hasReservation;
public StudentRecord(){
name = new String("");
rollNumber = 0;
departement = new String("");
totalMark = 0;
hasReservation = false;
}
public String toString() {
return "[" + departement+ ","+ name + "," + rollNumber +"]";
}
}
Main class is as shown below
Test.java
package com.test;
public class Test {
public native static StudentRecord[] getStudentDetails();
public static void main(String[] args) {
System.loadLibrary("Sample");
int a= 10;
StudentRecord[] records = getStudentDetails();
for(StudentRecord record:records){
System.out.println("Name:"+record.name);
System.out.println("Roll Number:"+record.rollNumber);
System.out.println("Departement:"+record.departement);
System.out.println("Total Marks:"+record.totalMark);
System.out.println("Has Reservation:"+record.hasReservation);
}
}
}
Next step would be to generate native method header file from java code.
as you know java has a tool javah for it, following figure shows the command.
The above command generates com_test_Test.h as shwown below.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_Test */
#ifndef _Included_com_test_Test
#define _Included_com_test_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_Test
* Method: getStudentDetails
* Signature: ()[Lcom/test/StudentRecord;
*/
JNIEXPORT jobjectArray JNICALL Java_com_test_Test_getStudentDetails
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
Implementation of JNI method is shown below
Sample.cpp
#include<stdafx.h>
#include<string>
#include<vector>
#include "com_test_Test.h"
typedef struct _JNI_POSREC {
jclass cls;
jmethodID constructortorID;
jfieldID nameID;
jfieldID rollNumberID;
jfieldID departementID;
jfieldID totalMarkID;
jfieldID hasReservationID;
} JNI_POSREC;
/**
* Return Search class.
*/
struct SearchRecord {
std::string name;
int rollNumber;
std::string departement;
float totalMark;
bool hasReservation;
};
JNI_POSREC * jniPosRec = NULL;
/**
* Fills the Student Record Details.
*/
void FillStudentRecordDetails(std::vector<SearchRecord*>* searchRecordResult ){
SearchRecord *pRecord1 = new SearchRecord();
pRecord1->name = "Ram";
pRecord1->rollNumber = 1;
pRecord1->departement = "Computer Science";
pRecord1->totalMark = 512.500;
pRecord1->hasReservation = true;
searchRecordResult->push_back(pRecord1);
SearchRecord *pRecord2 = new SearchRecord();
pRecord2->name = "Raju";
pRecord2->rollNumber = 2;
pRecord2->departement = "Electronics";
pRecord2->totalMark = 572.25;
pRecord2->hasReservation = false;
searchRecordResult->push_back(pRecord2);
}
/**
* Fills JNI details.
*/
void LoadJniPosRec(JNIEnv * env) {
if (jniPosRec != NULL)
return;
jniPosRec = new JNI_POSREC;
jniPosRec->cls = env->FindClass("com/test/StudentRecord");
if(jniPosRec->cls != NULL)
printf("sucessfully created class");
jniPosRec->constructortorID = env->GetMethodID(jniPosRec->cls, "<init>", "()V");
if(jniPosRec->constructortorID != NULL){
printf("sucessfully created ctorID");
}
jniPosRec->nameID = env->GetFieldID(jniPosRec->cls, "name", "Ljava/lang/String;");
jniPosRec->rollNumberID = env->GetFieldID(jniPosRec->cls, "rollNumber", "I");
jniPosRec->departementID = env->GetFieldID(jniPosRec->cls, "departement", "Ljava/lang/String;");
jniPosRec->totalMarkID = env->GetFieldID(jniPosRec->cls, "totalMark", "F");
jniPosRec->hasReservationID = env->GetFieldID(jniPosRec->cls, "hasReservation", "Z");
}
void FillStudentRecValuesToJni(JNIEnv * env, jobject jPosRec, SearchRecord* cPosRec) {
env->SetObjectField(jPosRec, jniPosRec->nameID, env->NewStringUTF(cPosRec->name.c_str()));
jint rollNum = (jint)cPosRec->rollNumber;
env->SetIntField(jPosRec, jniPosRec->rollNumberID, rollNum);
env->SetObjectField(jPosRec, jniPosRec->departementID, env->NewStringUTF(cPosRec->departement.c_str()));
jfloat totalMark = (jfloat)cPosRec->totalMark;
env->SetFloatField( jPosRec, jniPosRec->totalMarkID, totalMark);
jboolean hasReservation = cPosRec->hasReservation;
env->SetBooleanField( jPosRec, jniPosRec->hasReservationID, hasReservation);
}
/**
* JNI method calling from JAVA
*/
JNIEXPORT jobjectArray JNICALL Java_com_test_Test_getStudentDetails( JNIEnv *env, jclass cls)
{
jniPosRec = NULL;
LoadJniPosRec(env);
std::vector<SearchRecord*> searchRecordResult ;
FillStudentRecordDetails(&searchRecordResult);
printf("\nsearchRecordResult size is"+searchRecordResult.size());
jobjectArray jPosRecArray = env->NewObjectArray(searchRecordResult.size(), jniPosRec->cls, NULL);
for (size_t i = 0; i < searchRecordResult.size(); i++) {
jobject jPosRec = env->NewObject(jniPosRec->cls, jniPosRec->constructortorID);
FillStudentRecValuesToJni(env, jPosRec, searchRecordResult[i]);
env->SetObjectArrayElement(jPosRecArray, i, jPosRec);
}
return jPosRecArray;
}