一、从Java调用C++的DLL 1. 创建Java文件 创建名为TestNative的Java文件,注意包名。 package org.druze.test; publicclass TestNative { publicnativevoid sayHello(); publicvoid sayHello2(){ System.out.println("Say Hello From Java"); } } 如代码所示,对于sayHello方法声明为native,这一部分将由C++的动态库来实现。 2. 生成class文件 使用javac org/druze/test/TestNative.java生成class文件 注意:执行该命令在org所在目录执行。 3. 使用javah命令生成相应的C++头文件 使用javah org.druze.test.TestNative生成名为 org_druze_test_TestNative.h的头文件 注意:执行该命令在org所在目录执行。 该头文件的内容如下: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class org_druze_test_TestNative */ #ifndef _Included_org_druze_test_TestNative #define _Included_org_druze_test_TestNative #ifdef __cplusplus extern "C" { #endif /* * Class: org_druze_test_TestNative * Method: sayHello * Signature: ()V */ JNIEXPORT void JNICALL Java_org_druze_test_TestNative_sayHello (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 4. 创建C++解决方案 此处以VS2008为例。 新建一个VC++的Win32项目,选择如图所示的控制台应用程序。项目名称为NativeCode。 点击确定后,再点击下一步,出现该页面,应用程序类型选择DLL,附加选项选择DLL 5. 创建号工程之后,将org_druze_test_TestNative.h导入到工程里面,并创建名为source.cpp的源代码,内容如下: #include"org_druze_test_TestNative.h" #include<iostream> using namespace std; JNIEXPORT void JNICALL Java_org_druze_test_TestNative_sayHello(JNIEnv *env, jobject obj) { cout<<"Hello World!"<<endl; } 6. 在工具->选项->项目和解决方案->VC++目录菜单中,平台选择Win32,选择“显示以下内容的目录”为“包含文件”,导入jni.h和jni_md.h的路径。 7. 编译,生成NativeCode.dll,并将其copy到环境变量PATH的路径下。 8. 修改TestNative.java package org.druze.test; publicclass TestNative { publicnativevoid sayHello(); publicstaticvoid main(String[] args) { // 加载动态连接库DLL,如果没有找到的话,则会在运行时报错 System.loadLibrary("NativeCode");
TestNative tnt = new TestNative();
tnt.sayHello(); } publicvoid sayHello2(){ System.out.println("Say Hello From Java"); } } 运行,显示“Hello World!” 9. 注意头文件jni.h和jni_md.h可以直接导入到工程中也可以。 10.注意NativeCode.dll必须放置在java命令能访问的路径中。 二、从C++调用Java 1.创建TestNative2.Java package org.druze.test; publicclass TestNative2 { publicstaticvoid testPrint(){ System.out.println("this is from static method"); } publicstaticint testReturn(){ return 22; } publicstaticint testInput(int number){ return 22+number; } publicint testInstance(int number){ System.out.println("this is from instance method"); return 11+number; } } 2.在VS2008中创建win32控制台的应用程序,命名为NativeCode2,在向导中选择空项目。 3. 在工具->选项->项目和解决方案->VC++目录菜单中,平台选择Win32,选择“显示以下内容的目录”为“包含文件”,导入jni.h和jni_md.h的路径。或直接把jni.h和jni_md.h导入到工程中。 4. 在工具->选项->项目和解决方案->VC++目录菜单中,平台选择Win32,选择“显示以下内容的目录”为“包含文件”,导入jvm.lib的路径,并在项目->NativeCode2属性->配置属性->链接器->命令行中添加jvm.lib(这一步或者使用#pragma comment(lib,"jvm.lib")来代替)。或者将直接将jvm.lib添加到工程中。 5.创建Test.cpp #include <jni.h> #include <iostream> using namespace std; int main() { JavaVMOption options[1]; JNIEnv * env; JavaVM * jvm; JavaVMInitArgs vm_args; options[0].optionString = "-Djava.class.path=."; vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = 1; vm_args.options = options; vm_args.ignoreUnrecognized = JNI_TRUE; long status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); if (status == JNI_ERR) { cout<<"Can not create JVM"<<endl; return -1; } printf("Created JVM"n"); jclass cls = env->FindClass("org/druze/test/TestNative2"); printf("getCls"n"); cout<<cls<<endl; if (cls !=0) { jmethodID mid = env->GetStaticMethodID(cls, "testReturn", "()I"); printf("getMid"n"); if (mid !=0) { printf("testReturn"n"); int result=env->CallStaticIntMethod(cls, mid); printf("call over result=%d"n",result); } mid = env->GetStaticMethodID(cls, "testPrint", "()V"); if (mid !=0) { printf("testPrint"n"); env->CallStaticVoidMethod(cls, mid); } mid = env->GetStaticMethodID(cls, "testInput", "(I)I"); if (mid !=0) { printf("testInput"n"); int result=env->CallStaticIntMethod(cls, mid,22); printf("call over result=%d"n",result); } mid = env->GetMethodID(cls,"<init>","()V"); if (mid != 0)//获取方法成功 { printf("ctro!=0"n"); jobject obj=env->NewObject(cls, mid); printf("new object"n"); mid = env->GetMethodID(cls, "testInstance","(I)I"); if (mid!=0)//获取方法成功 { printf("methodID!=0"n"); jint result=env->CallIntMethod( obj, mid,22); cout<<result<<endl; } } } jvm->DestroyJavaVM(); system("Pause"); return 0; } 6.将jvm.dll目录添加到PATH环境变量中,将org/druze/test/TestNative2复制到debug目录下执行。 7.头文件和库文件的配置VC6和VC2008类似,菜单名称有所改变。 VC6中,配置头文件和库文件的目录在,工具(Tools)->选项(Options)->目录(Directories)里面的头文件”Include files”和库文件”Library files”.添加相应的目录 工程(Project)->设置(Setting)->链接(Link)->object/module library后面添加jvm.lib CodeBlocks在Project->Build options->Linker setting and Search directories中配置相应路径。 8.按如下结构组织可不用配置jvm.dll到环境变量中 创建存放目录Run(下面的文件目录在JDK安装目录中都能找倒): Run(手工建立目录) ----bin(手工建立目录) ----classic(手工建立目录) ----jvm.dll(文件,JDK安装目录中有) ----自己的JAR包,如果是class文件把包目录和文件一起拷贝过来 如果是jar文件,需要在options[1].optionString = "-Djava.class.path=.;./swt.jar";中设置 ----JniC.exe,C调用JAVA的程序 ----hpi.dll(文件,JDK安装目录中有) ----ioser12.dll(文件,JDK安装目录中有) ----java.dll(文件,JDK安装目录中有) ----net.dll(文件,JDK安装目录中有) ----verify.dll(文件,JDK安装目录中有) ----zip.dll(文件,JDK安装目录中有) ----lib(手工建立目录) ----zi(目录,JDK安装目录中有,全部拷贝过来) ----rt.jar(文件,JDK安装目录中有) ----tzmappings(文件,JDK安装目录中有) 三、JNI代码分析(待续) (###) |
|