半个月以前是打算写一些学习HTML的学习笔记的,后来想想现在网上关于HTML的学习网页这么多,就觉得没必要了。所以就不写了。
两天前,朋友找我帮忙,让我帮他实现在java中调用c语言中的函数,说白了就是做一个动态链接库(.dll)。我一看他传给我的源代码,差点吓尿啊——500多个函数啊。
可能函数多,所有遇到的类型转换比较全,我就在这里总结一下吧。
做这种借口一点都不难,无非就是数据类型匹配的问题。JNI中有很多种类型,其中的基本类型就有和c语言中的类型完全匹配的,网上有很多介绍这里就不多说了。来进入正题吧(PS:那些将.java转换成.h的方法等这里就不赘述了):
1、最常见的就是jstring和char*,之间的转换了。
1)jstring转换为char*
JNIEXPORT jint JNICALL Java_testENopen_Jepanet2_ENsaveinpfile
(JNIEnv *env, jobject _obj, jstring _str)
{
char* f1 = (*env)->GetStringUTFChars(env,_str,0);
int result = ENsaveinpfile(f1);
(*env)->ReleaseStringUTFChars(env,_str,f1);
printf("%s",f1);
return result;
}
因为我有方法实现的源码,就在实现的时候就少了很多不必要的加载和查找代码,直接调用方法ENsaveinpfile(f1)就可以了。这不是重点,重点是jstring和char*之间的转换 。通常调用过方法GetStringUTFChars()后,都要在调用方法ReleaseStringUTFChars(),不然就造成了内存的浪费。
2)char* 转换为jstring
JNIEXPORT jstring JNICALL Java_testENopen_Jepanet2_ENgetpatternid
(JNIEnv *env, jobject _obj, jint Inum)
{
jstring _str = (jstring)malloc(sizeof(jstring));
char* result = (*env)->GetStringUTFChars(env,_str,0);
int resultcode = ENgetpatternid(Inum,result);
jstring strReturn = (*env)->NewStringUTF(env,result);
(*env)->ReleaseStringUTFChars(env,_str,result);
printf("error code:%d\n",resultcode);
return strReturn;
}
这里可能写的有点麻烦了,不过测试过了。
2、 jintArray 和 int * ( int[ ] )之间的转换(jFloatArray 和 float*, jDoubleArray 和 double*之间的转换相似)
1)int* 转成 jintArray
JNIEXPORT jintArray JNICALL Java_testENopen_Jepanet2_ENgetqualtype
(JNIEnv *env, jobject _obj)
{
jintArray result = (*env)->NewIntArray(env,2);
int temp[2];
int resultCode = ENgetqualtype(&(temp[0]),&(temp[1]));
printf("error code:%d\n",resultCode);
(*env)->SetIntArrayRegion(env,result,0,2,temp);
return result;
}
这里NewIntArray()是初试化jintArray,方法SetIntArrayRegion()则是给jintArray result赋值。
2)jintArray转换成int*等同于jDoubleArray 和 double*之间的转换
JNIEXPORT jdouble JNICALL Java_testENopen_funcs_interp
(JNIEnv *env, jobject _obj, jint Inum, jdoubleArray dNum1, jdoubleArray dNum2, jdoubleArray dNum3)
{
double *temp1 = (*env)->GetDoubleArrayElements(env,dNum1,0);
double *temp2 = (*env)->GetDoubleArrayElements(env,dNum2,0);
double *temp3 = (*env)->GetDoubleArrayElements(env,dNum3,0);
double result = interp(Inum,temp1,temp2,temp3);
(*env)->ReleaseDoubleArrayElements(env,dNum1,temp1,0);
(*env)->ReleaseDoubleArrayElements(env,dNum1,temp1,0);
(*env)->ReleaseDoubleArrayElements(env,dNum1,temp1,0);
return result;
}
只要换相应的方法就可以了。
3、看看最麻烦的,char** 和string[](jobjectArray)之间的转换
JNIEXPORT jint JNICALL Java_testENopen_funcs_findmatch
(JNIEnv *env, jobject _obj, jstring _str, jobjectArray _strS)
{
jstring jstr;
int result;
char* temp = (*env)->GetStringUTFChars(env, _str, 0);
jsize len = (*env)->GetArrayLength(env, _strS);
int i=0;
char **pstr = (char **) malloc(len*sizeof(char *));
for (i=0 ; i
pstr[i] = (*env)->GetStringUTFChars(env, jstr, 0);
}
result = findmatch(temp,pstr);
for(i=0;i
jstr = (jstring)(*env)->GetObjectArrayElement(env, _strS, i);
(*env)->ReleaseStringUTFChars(env,jstr,pstr[i]);
}
return result;
}
不解释了,我看着也是醉了。。。。但是理解起来应该不难!
4、返回jobjectArray(int [][])
这里只写一些主要的方法吧(不贴原方法了,有点长):
jclass IntClass = (*env)->NewIntArray(env,Inum);
jobjectArray result = (*env)->NewObjectArray(env,3,IntClass,NULL);
int *temp1 = (*env)->GetIntArrayElements(env,IArr1,0); //IArr1是jIntArray型的
int *temp2 = (*env)->GetIntArrayElements(env,IArr1,0); //IArr2是jIntArray型的
int *temp3 = (*env)->GetIntArrayElements(env,IArr1,0); //IArr3是jIntArray型的
jintArray result1 = (*env)->NewIntArray(env,Inum);
jintArray result2 = (*env)->NewIntArray(env,Inum);
jintArray result3 = (*env)->NewIntArray(env,Inum);
(*env)->SetIntArrayRegion(env,result1,0,Inum,temp1);
(*env)->SetIntArrayRegion(env,result2,0,Inum,temp2);
(*env)->SetIntArrayRegion(env,result3,0,Inum,temp3);
(*env)->SetObjectArrayElement(env,result,0,result1);
(*env)->SetObjectArrayElement(env,result,1,result2);
(*env)->SetObjectArrayElement(env,result,2,result3);
(*env)->ReleaseIntArrayElements(env,IArr1,temp1,0);
(*env)->ReleaseIntArrayElements(env,IArr2,temp2,0);
(*env)->ReleaseIntArrayElements(env,IArr3,temp3,0);
过程大致是将jIntArray 转换成int*,然后将int*带入方法中(省,没贴出来),然后再将int*->jIntArray,最后将jIntArray添加到jobjectArray result中。
大致的类型转换也就这样了,其他的大同小异。
最后我还是说一下那个javah的命令行吧。因为我的java工程是有包的,所以这样写:
javah -classpath "到工程src的路径(如:G:\dir1\dir2\dir3\src)" package.XXX
结束。。。。。。