上次对JNI(Java Native Interface)调用做了个简单的介绍,在Java中调用C/C++的方法中,所有的方法都没有传递任何参数。考虑到Java和C/C++之间的String等类型的区别(具体区别请参考别的文章),通过查询JDK1.6的JNI相关api和docs的函数说明,对在方法中调用参数进行了测试,本次测试主要是jstring和char *之间的相互转换的函数:具体的转换代码如下:
char* jstringTocharStar(JNIEnv *env, jstring jstr) { char *rtn = NULL; //1、获取一个类对象 jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //2、构造一个String对象,内容为"utf-8",作为CallObjectMethod方法中的编码字符串 jstring strencode = (*env)->NewStringUTF(env, "utf-8"); //3、获取对象或者接口实例的方法ID jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); //4、调用Call<type>Method来invoke方法getBytes(String charsetName),获取jbyteArray对象 jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); //5、返回jbyteArray对象的元素数量 jsize alen = (*env)->GetArrayLength(env, barr); //6、返回一个jbyte指针对象 jbyte *ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if(alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } (*env)->ReleaseByteArrayElements(env, barr, ba, 0); return rtn; }
然后修改C/C++中相应的调用函数内容:
/* * Class: org_clzps_JNICaller * Method: print * Signature: ()V */ JNIEXPORT void JNICALL _Java_org_clzps_JNICaller_print (JNIEnv *env, jobject jobj, jstring str) { char * pChar = NULL; pChar = jstringTocharStar(env, str); puts(pChar); }
最后在Java代码中:
package org.clzps;
public class JNICaller {
static {
System.loadLibrary("libTestJNI");
}
public JNICaller() {}
public native void print(String str);
}
以及:
package org.clzps;
import junit.framework.TestCase;
public class TestJNICaller extends TestCase {
public void testCase() {
JNICaller caller = new JNICaller();
caller.print("你好");
}
}