How to call Java code from C/C++
I wanted to call Java functions from C++ and searching in the internet I found some codes but seems lacking more details. What I will do here is to make it complete.
CALLING JAVA IN C++ USING MS VISUAL STUDIO 2008
Requirements:
-JDK ( I used jdk1.7.0_55 32bit)
-Visual Studio 2008
Procedure:
1. Add the library "jvm.lib". Remember this library exist when you install the JDK
2. Add the 2 path of the include files of the JDK
3. Add the library path
4. Create the Java source and compile them (javac * to compile everything in the folder). The source location in my MS Windows environment is D:\MyFiles\Downloads\Java Src\TestStruct
//HelloWorld.java
public class HelloWorld
{
public static void main(String args[])
{
System.out.println("Hello World!");
System.out.println("This is the main function in HelloWorld class");
}
public static void TestCall(String szArg)
{
System.out.println(szArg);
}
public static int DisplayStruct(ControlNEDetail ctrlDetail)
{
System.out.println("Structure is:\n-------------------------");
System.out.println("Name:" + ctrlDetail.Name);
System.out.println("IP:" + ctrlDetail.IP);
System.out.println("Port" + ctrlDetail.Port);
return 1;
}
public static void DisplayStructArray(WorkOrder ArrWO[])
{
System.out.println("WorkOrders are Given hereunder:\n----------------------------");
for(int i = 0; i< ArrWO.length;i++)
{
System.out.println("<---work i="" number:="" order="" p="" string.valueof=""> System.out.println("Sum_Serial_ID: " + ArrWO[i].sumSerialId);
System.out.println("Access_Number: " + ArrWO[i].accessNumber);
System.out.println("Action_Type: " + ArrWO[i].actionType);
System.out.println("Effective_Date: " + ArrWO[i].effectiveDate);
System.out.println("Fetch_Flag: " + ArrWO[i].fetchFlag);
System.out.println("Reason: " + ArrWO[i].reason);
System.out.println("Access_Source: " + ArrWO[i].accessSource);
}
}
public static Object ReturnObjFunc()
{
System.out.println("Going to return an object from java");
ReturnData RetData = new ReturnData(1,"Successfull function call");
return RetData;
}
}
//ControlNEDetail.java
public class ControlNEDetail
{
public int ID;
public String Name;
public String IP;
public int Port;
public ControlNEDetail(int nID, String szName, String szIP, int nPort)
{
this.ID = nID;
this.Name = szName;
this.IP = szIP;
this.Port = nPort;
}
}
//ReturnData.java
public class ReturnData
{
int returnValue;
String Log;
public ReturnData(int nRetVal, String szLog)
{
this.returnValue = nRetVal;
this.Log = szLog;
}
}
//WorkOrder.java
public class WorkOrder
{
String sumSerialId;
String accessNumber;
String actionType;
String effectiveDate;
String fetchFlag;
String reason;
String accessSource;
public WorkOrder(String szSumID,String szAccNum, String szActType, String szEffectDate, String fetchFlg, String szReason, String szAccSrc )
{
this.sumSerialId = szSumID;
this.accessNumber = szAccNum;
this.actionType = szActType;
this.effectiveDate = szEffectDate;
this.fetchFlag = fetchFlg;
this.reason = szReason;
this.accessSource = szAccSrc;
}
};
5. Create the C++ code,
#include "StdAfx.h"
#include <stdio.h>
#include <jni.h>
#include <string.h>
#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
#define USER_CLASSPATH "." /* where Prog.class is */
struct ControlDetail
{
int ID;
char Name[100];
char IP[100];
int Port;
};
struct WorkOrder
{
char sumSerialId[20];
char accessNumber[18];
char actionType[4];
char effectiveDate[24];
char fetchFlag[2];
char reason[456];
char accessSource[100];
};
JNIEnv* create_vm(JavaVM ** jvm) {
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options;
options.optionString = "-Djava.class.path=D:\\MyFiles\\Downloads\\Java Src\\TestStruct;D:\\MyFiles\\RetailPlatform\\rpscom\\ExternalLibs\\JavaPOS\\1.13.2\\dist\\jpos1132.jar"; //Path to the java source code
vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;
int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if(ret < 0)
printf("\nUnable to Launch JVM\n");
return env;
}
int main(int argc, char* argv[])
{
JNIEnv *env;
JavaVM * jvm;
env = create_vm(&jvm);
if (env == NULL)
return 1;
struct ControlDetail ctrlDetail;
ctrlDetail.ID = 11;
strcpy(ctrlDetail.Name,"HR-HW");
strcpy(ctrlDetail.IP,"10.32.164.133");
ctrlDetail.Port = 9099;
printf("Struct Created in C has values:\nID:%d\nName:%s\n IP:%s\nPort:%d\n",ctrlDetail.ID,ctrlDetail.Name,ctrlDetail.IP,ctrlDetail.Port);
/********************************************************/
struct WorkOrder WO[2];
strcpy(WO[0].sumSerialId,"2000");
strcpy(WO[0].accessNumber,"2878430");
strcpy(WO[0].actionType,"04");
strcpy(WO[0].effectiveDate,"25-12-2007 12:20:30 PM");
strcpy(WO[0].fetchFlag, "0");
strcpy(WO[0].reason,"Executed Successfully");
strcpy(WO[0].accessSource,"PMS");
strcpy(WO[1].sumSerialId,"1000");
strcpy(WO[1].accessNumber,"2878000");
strcpy(WO[1].actionType,"T4");
strcpy(WO[1].effectiveDate,"25-12-2007 11:20:30 PM");
strcpy(WO[1].fetchFlag,"0");
strcpy(WO[1].reason,"");
strcpy(WO[1].accessSource,"RMS");
jclass clsH=NULL;
jclass clsJ=NULL;
jclass clsC = NULL;
jclass clsW = NULL;
jclass clsR = NULL;
jmethodID midMain = NULL;
jmethodID midCalling = NULL;
jmethodID midDispStruct = NULL;
jmethodID midDispStructArr = NULL;
jmethodID midRetObjFunc = NULL;
jmethodID midCtrlDetConst = NULL;
jmethodID midWoConst = NULL;
jobject jobjDet = NULL;
jobject jobjRetData = NULL;
jobjectArray jobjWOArr = NULL;
//Obtaining Classes
clsH = env->FindClass("HelloWorld");
clsJ = env->FindClass("jpos/BaseControl");
clsC = env->FindClass("ControlDetail");
clsW = env->FindClass("WorkOrder");
//Obtaining Method IDs
if (clsH != NULL)
{
midMain = env->GetStaticMethodID(clsH, "main", "([Ljava/lang/String;)V");
midCalling = env->GetStaticMethodID(clsH,"TestCall","(Ljava/lang/String;)V");
midDispStruct = env->GetStaticMethodID(clsH,"DisplayStruct","(LControlDetail;)I");
midDispStructArr = env->GetStaticMethodID(clsH,"DisplayStructArray","([LWorkOrder;)V");
midRetObjFunc = env->GetStaticMethodID(clsH,"ReturnObjFunc","()Ljava/lang/Object;");
}
else
{
printf("\nUnable to find the requested class\n");
}
if(clsC != NULL)
{
//Get constructor ID for ControlDetail
midCtrlDetConst = env->GetMethodID(clsC, "", "(ILjava/lang/String;Ljava/lang/String;I)V");
}
else
{
printf("\nUnable to find the requested class\n");
}
if(clsW != NULL)
{
//Get Constructor ID for WorkOrder
midWoConst = env->GetMethodID(clsW, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
}
else
{
printf("\nUnable to find the requested class\n");
}
/************************************************************************/
/* Now we will call the functions using the their method IDs */
/************************************************************************/
if(midMain != NULL)
env->CallStaticVoidMethod(clsH, midMain, NULL); //Calling the main method.
if (midCalling!=NULL)
{
jstring StringArg = env->NewStringUTF("\nTestCall:Called from the C Program\n");
//Calling another static method and passing string type parameter
env->CallStaticVoidMethod(clsH,midCalling,StringArg);
}
printf("\nGoing to Call DisplayStruct\n");
if (midDispStruct!=NULL)
{
if(clsC != NULL && midCtrlDetConst != NULL)
{
jstring StringArgName = env->NewStringUTF(ctrlDetail.Name);
jstring StringArgIP = env->NewStringUTF(ctrlDetail.IP);
//Creating the Object of ControlDetail.
jobjDet = env->NewObject(clsC, midCtrlDetConst, (jint)ctrlDetail.ID, StringArgName, StringArgIP, (jint)ctrlDetail.Port);
}
if(jobjDet != NULL && midDispStruct != NULL)
env->CallStaticIntMethod(clsH,midDispStruct,jobjDet); //Calling the method and passing ControlDetail Object as parameter
}
//Calling a function from java and passing Structure array to it.
printf("\n\nGoing to call DisplayStructArray From C\n\n");
if (midDispStructArr!=NULL)
{
if(clsW != NULL && midWoConst != NULL)
{
//Creating the Object Array that will contain 2 structures.
jobjWOArr = (jobjectArray)env->NewObjectArray(2,clsW,env->NewObject(clsW, midWoConst,env->NewStringUTF(""),env->NewStringUTF(""),env->NewStringUTF(""),
env->NewStringUTF(""),env->NewStringUTF(""),env->NewStringUTF(""),env->NewStringUTF("")));
//Initializing the Array
for(int i=0;i<2 i="" p=""> {
env->SetObjectArrayElement(jobjWOArr,i,env->NewObject(clsW, midWoConst,env->NewStringUTF(WO[i].sumSerialId),
env->NewStringUTF(WO[i].accessNumber),
env->NewStringUTF(WO[i].actionType),
env->NewStringUTF(WO[i].effectiveDate),
env->NewStringUTF(WO[i].fetchFlag),
env->NewStringUTF(WO[i].reason),
env->NewStringUTF(WO[i].accessSource)));
}
}
//Calling the Static method and passing the Structure array to it.
if(jobjWOArr != NULL && midDispStructArr != NULL)
env->CallStaticVoidMethod(clsW,midDispStructArr,jobjWOArr);
}
//Calling a Static function that return an Object
if (midRetObjFunc != NULL)
{
//Calling the function and storing the return object into jobject type variable
//Returned object is basically a structure having two fields (string and integer)
jobjRetData = (jobject)env->CallStaticObjectMethod(clsH,midRetObjFunc,NULL);
//Get the class of object
clsR = env->GetObjectClass(jobjRetData);
//Obtaining the Fields data from the returned object
jint nRet = env->GetIntField(jobjRetData,env->GetFieldID(clsR,"returnValue","I"));
jstring jstrLog = (jstring)env->GetObjectField(jobjRetData,env->GetFieldID(clsR,"Log","Ljava/lang/String;"));
const char *pLog = env->GetStringUTFChars(jstrLog,0);
printf("\n\nValues Returned from Object are:\nreturnValue=%d\nLog=%s",nRet,pLog);
//After using the String type data release it.
env->ReleaseStringUTFChars(jstrLog,pLog);
}
//Release resources.
int n = jvm->DestroyJavaVM();
return 0;
}
6. Output
2>---work>
3. Add the library path
4. Create the Java source and compile them (javac * to compile everything in the folder). The source location in my MS Windows environment is D:\MyFiles\Downloads\Java Src\TestStruct
//HelloWorld.java
public class HelloWorld
{
public static void main(String args[])
{
System.out.println("Hello World!");
System.out.println("This is the main function in HelloWorld class");
}
public static void TestCall(String szArg)
{
System.out.println(szArg);
}
public static int DisplayStruct(ControlNEDetail ctrlDetail)
{
System.out.println("Structure is:\n-------------------------");
System.out.println("Name:" + ctrlDetail.Name);
System.out.println("IP:" + ctrlDetail.IP);
System.out.println("Port" + ctrlDetail.Port);
return 1;
}
public static void DisplayStructArray(WorkOrder ArrWO[])
{
System.out.println("WorkOrders are Given hereunder:\n----------------------------");
for(int i = 0; i< ArrWO.length;i++)
{
System.out.println("Access_Number: " + ArrWO[i].accessNumber);
System.out.println("Action_Type: " + ArrWO[i].actionType);
System.out.println("Effective_Date: " + ArrWO[i].effectiveDate);
System.out.println("Fetch_Flag: " + ArrWO[i].fetchFlag);
System.out.println("Reason: " + ArrWO[i].reason);
System.out.println("Access_Source: " + ArrWO[i].accessSource);
}
}
public static Object ReturnObjFunc()
{
System.out.println("Going to return an object from java");
ReturnData RetData = new ReturnData(1,"Successfull function call");
return RetData;
}
}
//ControlNEDetail.java
public class ControlNEDetail
{
public int ID;
public String Name;
public String IP;
public int Port;
public ControlNEDetail(int nID, String szName, String szIP, int nPort)
{
this.ID = nID;
this.Name = szName;
this.IP = szIP;
this.Port = nPort;
}
}
//ReturnData.java
public class ReturnData
{
int returnValue;
String Log;
public ReturnData(int nRetVal, String szLog)
{
this.returnValue = nRetVal;
this.Log = szLog;
}
}
//WorkOrder.java
public class WorkOrder
{
String sumSerialId;
String accessNumber;
String actionType;
String effectiveDate;
String fetchFlag;
String reason;
String accessSource;
public WorkOrder(String szSumID,String szAccNum, String szActType, String szEffectDate, String fetchFlg, String szReason, String szAccSrc )
{
this.sumSerialId = szSumID;
this.accessNumber = szAccNum;
this.actionType = szActType;
this.effectiveDate = szEffectDate;
this.fetchFlag = fetchFlg;
this.reason = szReason;
this.accessSource = szAccSrc;
}
};
5. Create the C++ code,
#include "StdAfx.h"
#include <stdio.h>
#include <jni.h>
#include <string.h>
#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
#define USER_CLASSPATH "." /* where Prog.class is */
struct ControlDetail
{
int ID;
char Name[100];
char IP[100];
int Port;
};
struct WorkOrder
{
char sumSerialId[20];
char accessNumber[18];
char actionType[4];
char effectiveDate[24];
char fetchFlag[2];
char reason[456];
char accessSource[100];
};
JNIEnv* create_vm(JavaVM ** jvm) {
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options;
options.optionString = "-Djava.class.path=D:\\MyFiles\\Downloads\\Java Src\\TestStruct;D:\\MyFiles\\RetailPlatform\\rpscom\\ExternalLibs\\JavaPOS\\1.13.2\\dist\\jpos1132.jar"; //Path to the java source code
vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;
int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if(ret < 0)
printf("\nUnable to Launch JVM\n");
return env;
}
int main(int argc, char* argv[])
{
JNIEnv *env;
JavaVM * jvm;
env = create_vm(&jvm);
if (env == NULL)
return 1;
struct ControlDetail ctrlDetail;
ctrlDetail.ID = 11;
strcpy(ctrlDetail.Name,"HR-HW");
strcpy(ctrlDetail.IP,"10.32.164.133");
ctrlDetail.Port = 9099;
printf("Struct Created in C has values:\nID:%d\nName:%s\n IP:%s\nPort:%d\n",ctrlDetail.ID,ctrlDetail.Name,ctrlDetail.IP,ctrlDetail.Port);
/********************************************************/
struct WorkOrder WO[2];
strcpy(WO[0].sumSerialId,"2000");
strcpy(WO[0].accessNumber,"2878430");
strcpy(WO[0].actionType,"04");
strcpy(WO[0].effectiveDate,"25-12-2007 12:20:30 PM");
strcpy(WO[0].fetchFlag, "0");
strcpy(WO[0].reason,"Executed Successfully");
strcpy(WO[0].accessSource,"PMS");
strcpy(WO[1].sumSerialId,"1000");
strcpy(WO[1].accessNumber,"2878000");
strcpy(WO[1].actionType,"T4");
strcpy(WO[1].effectiveDate,"25-12-2007 11:20:30 PM");
strcpy(WO[1].fetchFlag,"0");
strcpy(WO[1].reason,"");
strcpy(WO[1].accessSource,"RMS");
jclass clsH=NULL;
jclass clsJ=NULL;
jclass clsC = NULL;
jclass clsW = NULL;
jclass clsR = NULL;
jmethodID midMain = NULL;
jmethodID midCalling = NULL;
jmethodID midDispStruct = NULL;
jmethodID midDispStructArr = NULL;
jmethodID midRetObjFunc = NULL;
jmethodID midCtrlDetConst = NULL;
jmethodID midWoConst = NULL;
jobject jobjDet = NULL;
jobject jobjRetData = NULL;
jobjectArray jobjWOArr = NULL;
//Obtaining Classes
clsH = env->FindClass("HelloWorld");
clsJ = env->FindClass("jpos/BaseControl");
clsC = env->FindClass("ControlDetail");
clsW = env->FindClass("WorkOrder");
//Obtaining Method IDs
if (clsH != NULL)
{
midMain = env->GetStaticMethodID(clsH, "main", "([Ljava/lang/String;)V");
midCalling = env->GetStaticMethodID(clsH,"TestCall","(Ljava/lang/String;)V");
midDispStruct = env->GetStaticMethodID(clsH,"DisplayStruct","(LControlDetail;)I");
midDispStructArr = env->GetStaticMethodID(clsH,"DisplayStructArray","([LWorkOrder;)V");
midRetObjFunc = env->GetStaticMethodID(clsH,"ReturnObjFunc","()Ljava/lang/Object;");
}
else
{
printf("\nUnable to find the requested class\n");
}
if(clsC != NULL)
{
//Get constructor ID for ControlDetail
midCtrlDetConst = env->GetMethodID(clsC, "
}
else
{
printf("\nUnable to find the requested class\n");
}
if(clsW != NULL)
{
//Get Constructor ID for WorkOrder
midWoConst = env->GetMethodID(clsW, "
}
else
{
printf("\nUnable to find the requested class\n");
}
/************************************************************************/
/* Now we will call the functions using the their method IDs */
/************************************************************************/
if(midMain != NULL)
env->CallStaticVoidMethod(clsH, midMain, NULL); //Calling the main method.
if (midCalling!=NULL)
{
jstring StringArg = env->NewStringUTF("\nTestCall:Called from the C Program\n");
//Calling another static method and passing string type parameter
env->CallStaticVoidMethod(clsH,midCalling,StringArg);
}
printf("\nGoing to Call DisplayStruct\n");
if (midDispStruct!=NULL)
{
if(clsC != NULL && midCtrlDetConst != NULL)
{
jstring StringArgName = env->NewStringUTF(ctrlDetail.Name);
jstring StringArgIP = env->NewStringUTF(ctrlDetail.IP);
//Creating the Object of ControlDetail.
jobjDet = env->NewObject(clsC, midCtrlDetConst, (jint)ctrlDetail.ID, StringArgName, StringArgIP, (jint)ctrlDetail.Port);
}
if(jobjDet != NULL && midDispStruct != NULL)
env->CallStaticIntMethod(clsH,midDispStruct,jobjDet); //Calling the method and passing ControlDetail Object as parameter
}
//Calling a function from java and passing Structure array to it.
printf("\n\nGoing to call DisplayStructArray From C\n\n");
if (midDispStructArr!=NULL)
{
if(clsW != NULL && midWoConst != NULL)
{
//Creating the Object Array that will contain 2 structures.
jobjWOArr = (jobjectArray)env->NewObjectArray(2,clsW,env->NewObject(clsW, midWoConst,env->NewStringUTF(""),env->NewStringUTF(""),env->NewStringUTF(""),
env->NewStringUTF(""),env->NewStringUTF(""),env->NewStringUTF(""),env->NewStringUTF("")));
//Initializing the Array
for(int i=0;i<2 i="" p=""> {
env->SetObjectArrayElement(jobjWOArr,i,env->NewObject(clsW, midWoConst,env->NewStringUTF(WO[i].sumSerialId),
env->NewStringUTF(WO[i].accessNumber),
env->NewStringUTF(WO[i].actionType),
env->NewStringUTF(WO[i].effectiveDate),
env->NewStringUTF(WO[i].fetchFlag),
env->NewStringUTF(WO[i].reason),
env->NewStringUTF(WO[i].accessSource)));
}
}
//Calling the Static method and passing the Structure array to it.
if(jobjWOArr != NULL && midDispStructArr != NULL)
env->CallStaticVoidMethod(clsW,midDispStructArr,jobjWOArr);
}
//Calling a Static function that return an Object
if (midRetObjFunc != NULL)
{
//Calling the function and storing the return object into jobject type variable
//Returned object is basically a structure having two fields (string and integer)
jobjRetData = (jobject)env->CallStaticObjectMethod(clsH,midRetObjFunc,NULL);
//Get the class of object
clsR = env->GetObjectClass(jobjRetData);
//Obtaining the Fields data from the returned object
jint nRet = env->GetIntField(jobjRetData,env->GetFieldID(clsR,"returnValue","I"));
jstring jstrLog = (jstring)env->GetObjectField(jobjRetData,env->GetFieldID(clsR,"Log","Ljava/lang/String;"));
const char *pLog = env->GetStringUTFChars(jstrLog,0);
printf("\n\nValues Returned from Object are:\nreturnValue=%d\nLog=%s",nRet,pLog);
//After using the String type data release it.
env->ReleaseStringUTFChars(jstrLog,pLog);
}
//Release resources.
int n = jvm->DestroyJavaVM();
return 0;
}
6. Output
2>---work>
Very nice example.. keep it up!
ReplyDelete