使用JNI,需要为C\C++生成JAVA调用约定头文件,并对标准windows DLL源码进行适当修改。以下以一个简单的例子演示整个过程。
环境:win7 64位操作系统,JDK1.7 64位,vs2010(安装x64编译支持)。
一,编写native声明的类
代码如下 | 复制代码 |
package com.ninecmd; public class MyClass { static { System.loadLibrary("jnidll"); } public native static void SayHello(String word); public native static String RepeatWord(String word); /*public static void main(String[] args) { SayHello("hello"); String str = RepeatWord("么么哒"); System.out.println(str); } */ } |
“SayHello”,“RepeatWord”为将来dll文件中的函数声明。这个类的作用是生成C\C++头文件
二,生成C\C++头文件
这里需要注意classpath的路径问题。本例中MyClass 类的完整路径为E:\src\com\ninecmd\MyClass.java,类的包名为com.ninecmd,所以classpath应设置为E:\src。
将cmd切换至E:\src。
1、编译MyClass,在同目录生成MyClass.class
代码如下 | 复制代码 |
E:\src>javac com\ninecmd\MyClass.java |
2、生成头文件(注意classpath路径设置)
代码如下 | 复制代码 |
E:\src>javah -classpath E:\src -d com\ninecmd\ -jni com.ninecmd.MyClass |
javah参数说明:
javah -classpath 类目录 -d 头文件输出目录 -jni 完整类名
此时在E:\src\com\ninecmd目录中生成了com_ninecmd_MyClass.h文件
代码如下 | 复制代码 |
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_ninecmd_MyClass */ #ifndef _Included_com_ninecmd_MyClass #define _Included_com_ninecmd_MyClass #ifdef __cplusplus extern "C" { #endif /* * Class: com_ninecmd_MyClass * Method: SayHello * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_com_ninecmd_MyClass_SayHello (JNIEnv *, jobject, jstring); /* * Class: com_ninecmd_MyClass * Method: RepeatWord * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_ninecmd_MyClass_RepeatWord (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif |
三,编写DLL代码
1、本例编写x64 DLL,打开vs2010,创建一个MFC DLL工程。将平台改为x64.
2、引入头文件,为了顺眼,我把头文件改名为MyClass.h。
3、编写与头文件声明一致的导出函数。
主要代码:
代码如下 | 复制代码 |
//将jstring类型转换成windows char*类型 char* jstringToChars( JNIEnv *env, jstring jstr ) { int length = (env)->GetStringLength(jstr ); const jchar* jcstr = (env)->GetStringChars(jstr, 0 ); char* rtn = (char*)malloc( length*2+1 ); int size = 0; size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL ); if( size <= 0 ) return NULL; (env)->ReleaseStringChars(jstr, jcstr ); rtn[size] = 0; return rtn; } //将windows char*类型转换成jstring类型 jstring CharsTojstring( JNIEnv* env, char* str ) { jstring rtn = 0; int slen = strlen(str); unsigned short * buffer = 0; if( slen == 0 ) rtn = (env)->NewStringUTF(str ); else { int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 ); buffer = (unsigned short *)malloc( length*2 + 1 ); if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 ) rtn = (env)->NewString( (jchar*)buffer, length ); } if( buffer ) free( buffer ); return rtn; } JNIEXPORT void JNICALL Java_com_ninecmd_MyClass_SayHello (JNIEnv *env, jobject obj, jstring jstr) { char* str = jstringToChars(env,jstr); CString out(str); AfxMessageBox((out)); } JNIEXPORT jstring JNICALL Java_com_ninecmd_MyClass_RepeatWord (JNIEnv *env, jobject obj, jstring jstr) { return jstr; } |
4、编译发布dll。
四,JNI调用dll
将生成的dll,修改文件名为jnidll.dll,复制到系统System32目录下。将第一步中类代码main函数注释去掉。重新编译类(为保证中文字符串兼容,代码文件需为ANSI编码),并运行测试。
或者用eclipse测试类
测试成功!
时间: 2024-09-20 00:58:15