c 调用 java 时,java 程序常常 是依赖多个jar包的,关键是 如何要告诉jvm jar包的路径。
先写c代码:
1 c代码
写调用JAVA 的C++ 代码(main.cpp)如下:
上面的代码中,
#include <iostream>
#include <jni.h>
#ifdef _WIN32
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif
using namespace std;
int main()
{
JavaVMOption options[3];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jint square;
jboolean not1;
jobject jobj;
options[0].optionString = "-Djava.class.path=/home/cInvokeJavaLinux/refjar";
options[1].optionString="-verbose:jni";
options[2].optionString="-Djava.ext.dirs=/home/cInvokeJavaLinux/refjar";
vm_args.version =JNI_VERSION_1_6;// JNI_VERSION_1_2;
vm_args.nOptions = 3;
vm_args.options = options;
/* options[0].optionString = "-Djava.class.path=.";
vm_args.version =JNI_VERSION_1_6;// JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
*/
status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
/*
if (status != JNI_ERR)
{
cls = env->FindClass("com/testJni/testDemo/C2java");
if(cls !=0)
{
mid = env->GetStaticMethodID( cls, "add", "(II)I");
if(mid !=0)
{
square = env->CallStaticIntMethod( cls, mid, 5,5);
std::cout << square << std::endl;
}
mid = env->GetMethodID(cls,"<init>","()V");
if(mid !=0)
{
jobj=env->NewObject(cls,mid);
std::cout << "init ok" << std::endl;
}
mid = env->GetMethodID( cls, "judge","(Z)Z");
if(mid !=0)
{
not = env->CallBooleanMethod(jobj, mid, 1);
if(!not){
std::cout << "Boolean ok" << std::endl;
}
}
}
jvm->DestroyJavaVM();
return 0;
}*/
if (status != JNI_ERR)
{
std::cout<<"JNI_CreateJavaVM sucess"<<std::endl;
cls = env->FindClass("V2ConfWebService");
if(cls !=0)
{
mid = env->GetStaticMethodID( cls, "getWebServiceResultConfID", "()I");
if(mid !=0)
{
int ret=env->CallStaticIntMethod( cls, mid);
std::cout << "end CallStaticIntMethod ret=" << ret<<std::endl;
}
/*
mid = env->GetMethodID(cls,"<init>","()V");
if(mid !=0)
{
jobj=env->NewObject(cls,mid);
std::cout << "init ok" << std::endl;
}
mid = env->GetMethodID( cls, "judge","(Z)Z");
if(mid !=0)
{
not = env->CallBooleanMethod(jobj, mid, 1);
if(!not){
std::cout << "Boolean ok" << std::endl;
}
}
*/
}
else
{
std::cout<<"calss V2ConfWebService not found"<<std::endl;
}
jvm->DestroyJavaVM();
return 0;
}
else
{
std::cout<<"JNI_CreateJavaVM failed"<<std::endl;
return -1;
}
}
java.class.path=/home/cInvokeJavaLinux/refjar
指定Java代码编译的类的存放的路径,但是这个选项没法指定多个jar包的路径。
最关键的是要使用,-Djava.ext.dirs=/home/cInvokeJavaLinux/refjar
指定多个jar包的路径。
在/home/cInvokeJavaLinux/refjar目录中,我们把我们写的java 的代码和所有引用的第三方的jar包都放到了这个目录中。
1.2 c代码的makefile
all:test
clean:
rm -rf test
test:
g++ -g -o test main.cpp -I/usr/java/jdk1.7.0/include -I/usr/java/jdk1.7.0/include/linux/ -L/usr/java/jdk1.7.0/jre/lib/i386/client/ -ljvm
上面的makefile中的/usr/java/jdk1.7.0/jre/lib/i386/client/ 是libjvm.so库的路径。
2 java 代码
下面我们写java 代码。
import org.apache.axis.client.Service;
import org.apache.axis.client.Call;
public class V2ConfWebService {
public static int getWebServiceResultConfID() {
try {
int retCode=-1;
String endpoint = "http://192.168.84.1:11080/Conf/" +
"services/ConferenceWebService?wsdl";
String method = "getWebServiceResult";
int number = 8000;
Service service = new Service();
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName(method);
call.getMessageContext().setUsername("v2com");
call.getMessageContext().setPassword("simple");
//
String xml =
"<?xml version='1.0' encoding='UTF-8'?>"+
"<Package confid='313151' webservicepwd=''/>";
Object[] s = new Object[]{number,xml,""};
String result = (String) call.invoke(s);
System.out.println(result);
// retCode= Integer.parseInt(result);
return 1984;
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex.toString());
return -1;
}
}
public static void main(String[] args ) {
//public static void getWebServiceResultConfID(String confid) {
try {
int retCode=-1;
String endpoint = "http://192.168.84.1:11080/Conf/" +
"services/ConferenceWebService?wsdl";
String method = "getWebServiceResult";
int number = 8000;
Service service = new Service();
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpoint));
call.setOperationName(method);
call.getMessageContext().setUsername("v2com");
call.getMessageContext().setPassword("simple");
//
String xml =
"<?xml version='1.0' encoding='UTF-8'?>"+
"<Package confid='313151' webservicepwd=''/>";
Object[] s = new Object[]{number,xml,""};
String result = (String) call.invoke(s);
System.out.println(result);
// retCode= Integer.parseInt(result);
//return retCode;
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex.toString());
// return -1;
}
}
}
这个java 代码在 eclipse中编译后,把bin 中的V2ConfWebService.class 文件和引用的jar 包 都拷贝到服务器上的
/home/cInvokeJavaLinux/refjar 目录。
3 编译执行
在/home/cInvokeJavaLinux目录中,执行make 编译得到test.
在写个脚本如下:
export LD_LIBRARY_PATH=/usr/java/jdk1.7.0/jre/lib/i386/client
./test
执行 这个脚本 就 得到 了C 调用JAVA 的结果。