#include "Sample1.h" #include <string.h> JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *env, jobject obj, jint num) { return num * num; } JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod (JNIEnv *env, jobject obj, jboolean boolean) { return !boolean; } JNIEXPORT jstring JNICALL Java_Sample1_stringMethod (JNIEnv *env, jobject obj, jstring string) { const char* str = (*env)->GetStringUTFChars(env, string, 0); char cap[128]; strcpy(cap, str); (*env)->ReleaseStringUTFChars(env, string, 0); return (*env)->NewStringUTF(env, strupr(cap)); } JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod (JNIEnv *env, jobject obj, jintArray array) { int i, sum = 0; jsize len = (*env)->GetArrayLength(env, array); jint *body = (*env)->GetIntArrayElements(env, array, 0); for (i = 0; i < len; ++i) { sum += body[i]; } (*env)->ReleaseIntArrayElements(env, array, body, 0); return sum; }
|
(*env)->GetStringUTFChars()这个方法, 是用来在Java和C之间转换字符串的, 由于Java自己都使用了双字节的字符, 而C语言自己都是单字节的字符, 因此须要进行转换.
JNIEnv *是每一个函数都有的参数, 它包含了不少有用的方法, 使用起来相似Java的反射, 也提供了这样一个编码转换的函数.
GetStringUTFChars()和NewStringUTF(), 第一个是从UTF8转换为C的编码格式, 第二个是根据C的字符串返回一个UTF8字符串.
ReleaseStringUTFChars()是用来释放对象的, 在Java中有虚拟机进行垃圾回收, 可是在C语言中, 这些对象必须手动回收. 不然可能形成内存泄漏.
函数的名字一眼看到就能够猜出功能, jni.h中的大部分函数名都是这样.
若是是C++的话, 这段代码该怎么写?
下面是C++的代码
#include "Sample1.h" #include <string.h> JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *env, jobject obj, jint num) { return num * num; } JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod (JNIEnv *env, jobject obj, jboolean boolean) { return !boolean; } JNIEXPORT jstring JNICALL Java_Sample1_stringMethod (JNIEnv *env, jobject obj, jstring string) { const char* str = env->GetStringUTFChars(string, 0); char cap[128]; strcpy(cap, str); env->ReleaseStringUTFChars(string, 0); return env->NewStringUTF(strupr(cap)); } JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod (JNIEnv *env, jobject obj, jintArray array) { int i, sum = 0; jsize len = env->GetArrayLength(array); jint *body = env->GetIntArrayElements(array, 0); for (i = 0; i < len; ++i) { sum += body[i]; } env->ReleaseIntArrayElements(array, body, 0); return sum; }
上述两端代码很是类似, 只有一个不一样点
C代码: (*env)->GetStringUTFChars(env, string, 0);
C++代码: env->GetStringUTFChars(string, 0);
C语言中使用的是结构体的函数指针, 而在C++中使用的仍是struct, 咱们知道struct在C++中和class的功能是几乎同样的, struct也能够用来定义类, 因此env在C++中是个类对象的指针.
这里使用的是微软编译器, 编译C语言版的dll
>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.c -FeSample1.dll
编译C++版本的dll
>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.cpp -FeSample1.dll
运行
>java Sample1
注意: 64位版本的JDK可能会在运行时报错:
java.lang.UnsatisfiedLinkError: ...Sample1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
若是您有这样的错误, 请使用32位的JDK来从新运行.
运行结果以下:
intMethod:
25
booleanMethod:
false
stringMethod: JAVA
intArrayMethod:
36
|
源代码下载: Sample1.zip
运行其中的build&run.bat文件便可, 若有错误请根据实际状况修改其中的一些参数.
DLL工程文件VC6.0和VS2010的: VC6.0&VS2010.zip
参考文献: