在《在java中如何使用native函数》一文中,讲述了java中native函数的使用方法,其中,列举的例子中,原生函数并没有带任何参数,也没有返回任何参数。那如果原生函数需要带一些参数或者需要返回一些参数,那又该如何实现呢?
我们知道,在java中之所以能够调用native函数,这主要由JNI机制来保证。
要回答本文开始提到的问题,就必须了解JNI机制的实现原理。
一、JNI机制的简单介绍
在java中调用由其他语言如C编写的函数,其需要解决的问题之一就是类型差异问题。
我们知道,java与C/C++中的数据类型并不一样,比如,在java中,调用native接口,如果该接口在java端传递一个String类型的数据,而在C端,并不认识由Java端传递过来的数据类型,这样,JNI必须实现:对Java和C/C++数据类型的适配,也就是JNI在Java端和C/C++端起到了一个桥梁的作用。
那该如何实现对Java和C/C++数据类型的适配呢,这主要是通过一个类型匹配表来实现:
基本数据类型的匹配表:
复合数据类型匹配:
注意:
1、JNI机制会根据上述匹配表将java端的数据类型映射为JNI数据类型
2、JNI中数据类型都以字母j开头
3、JNI中的基本数据类型可以和C/C++中对应的基本数据类型互换,即可以直接在C/C++ 中直接使用
4、JNI中复合数据类型不能在C/C++代码中直接使用,必须通过JNI的相关接口来转换为
C/C++中相应的数据类型,如可以使用JNI接口GetStringUTFChars来将JNI的复合数 据类型jstring转换为C/C++中的字符串
二、例子:在java中调用带参数的native函数
这里,我们只写出java端的代码和相应的C端的实现代码,具体步骤可见《在java中 如何使用native函数》。
Java端代码(文件名为testJniWithPara.java):
class testJniWithPara
{
//native函数:将参数所表示的字符串由大写字母转换为小写字母并返回
public native static String myToLower(String upper);
static
{
System.loadLibrary("toLower");
}
public static void main(String args[])
{
System.out.println("I'm in Java, the return string form C is : " + myToLower("THIS IS FROM JAVA!"));
}
}
C端代码(文件名为testJniWithPara.c):
#include
#include
#include
#include "testJniWithPara.h"
JNIEXPORT jstring JNICALL Java_testJniWithPara_myToLower
(JNIEnv *env, jclass clazz, jstring param)
{
//在java端,该native函数声明时,参数为String类型,而这里,已经变为了
//jstring类型,这都是JNI根据类型匹配表转换的
//由于这里传递的是复合数据类型,在C中不能直接使用,而需要使用JNI提供的 //方法GetStringUTFChars来将JNI数据类型转换为C中相应的数据类型
const jbyte *str = (const jbyte*)env->GetStringUTFChars(param, NULL);
if (NULL == str)
{
printf("error, when calling GetStringUTFChars/n");
return NULL;
}
printf("I'm in C, the param from java is : %s/n", str);
//大写字母转换为小写字母
char buf[256];
strcpy(buf, (const char*)str);
int i, len = strlen(buf);
for (i = 0; i < len; i++)
{
buf[i] = (char)tolower((int)buf[i]);
}
//字符串str使用完毕之后需要调用JNI接口ReleaseStringUTFChars释放掉
env->ReleaseStringUTFChars(param, (const char*)str);
//调用JNI接口NewStringUTF将转换后的字符串返回到Java端
return env->NewStringUTF(buf);
}
这样,就实现了数据在Java端和C端的相互传递,当然,这里只是演示了String类型 数据的交互,其他复合数据类型的交互也类似。主要需要用到JIN的一些接口来做数据 类型的转换,比如对于字符串类型,就是GetStringUTFChars和NewStringUTF。
参考资料:http://blog.csdn.net/chenjie19891104/archive/2011/05/11/6412471.aspx