· [Java论坛][安全论坛][数据库论坛][操作系统论坛]
· [访谈] 网银安全系列访谈之:惊心动魄网银故事
· [热点专题] 网银安全系列 3G上网卡巡礼
· [订阅IT技术周刊][IT资源下载专区][病毒求助专区]
· [热点] 跨站脚本十二问 四步防范Conficker
· [热点] Windows 7 RC版公开下载 憾缺中文版

如何在C/C++中调用Java (2)

发布时间:2003.02.17 10:01     来源:开放系统世界——赛迪网    作者:刘冬

这两个函数的区别在于GetStaticMethodID是用来获取静态方法的定义,GetMethodID则是获取非静态的方法定义。这两个函数都需要提供四个参数:env就是初始化虚拟机得到的JNI环境;第二个参数class是对象的类定义,也就是第一步得到的obj;第三个参数是方法名称;最重要的是第四个参数,这个参数是方法的定义。因为我们知道Java中允许方法的多态,仅仅是通过方法名并没有办法定位到一个具体的方法,因此需要第四个参数来指定方法的具体定义。但是怎么利用一个字符串来表示方法的具体定义呢?JDK中已经准备好一个反编译工具javap,通过这个工具就可以得到类中每个属性、方法的定义。下面就来看看jni.test.Demo的定义:

打开命令行窗口并运行 javap -s -p jni.test.Demo 得到运行结果如下:

Compiled from Demo.java
public class jni.test.Demo extends java.lang.Object {
 public static int COUNT;
 /*   I   */
 public java.lang.String msg;
 /*   Ljava/lang/String;   */
 private int counts[];
 /*   [I   */
 public jni.test.Demo();
 /*   ()V   */
 public jni.test.Demo(java.lang.String);
 /*   (Ljava/lang/String;)V   */
 public java.lang.String getMessage();
 /*   ()Ljava/lang/String;   */
 public int getCounts()[];
 /*   ()[I   */
 public void setCounts(int[]);
 /*   ([I)V   */
 public void throwExcp() throws java.lang.IllegalAccessException;
 /*   ()V   */
 static {};
 /*   ()V   */
}

我们看到类中每个属性和方法下面都有一段注释。注释中不包含空格的内容就是第四个参数要填的内容(关于javap具体参数请查询JDK的使用帮助)。下面这段代码演示如何访问jni.test.Demo的getMessage方法:

/*
假设我们已经有一个jni.test.Demo的实例obj 
*/
jmethodID mid;
jclass cls = (*env)-> GetObjectClass (env, obj);	//获取实例的类定义
mid=(*env)->GetMethodID(env,cls,"getMessage"," ()Ljava/lang/String; ");
/*如果mid为0表示获取方法定义失败*/
jstring msg = (*env)-> CallObjectMethod(env, obj, mid);
/*
如果该方法是静态的方法那只需要将最后一句代码改为以下写法即可:
jstring msg = (*env)-> CallStaticObjectMethod(env, cls, mid);
*/

3.调用方法

为了调用对象的某个方法,可以使用函数Call<TYPE>Method或者CallStatic<TYPE>Method(访问类的静态方法),<TYPE>根据不同的返回类型而定。这些方法都是使用可变参数的定义,如果访问某个方法需要参数时,只需要把所有参数按照顺序填写到方法中就可以。在讲到构造函数的访问时,将演示如何访问带参数的构造函数。

访问类属性

访问类的属性与访问类的方法大体上是一致的,只不过是把方法变成属性而已。

1.获取指定对象的类(jclass)

这一步与访问类方法的第一步完全相同,具体使用参看访问类方法的第一步。

2.读取类属性的定义(jfieldID)

在JNI中是这样定义获取类属性的方法的:

jfieldID (JNICALL *GetFieldID)
(JNIEnv *env, jclass clazz, const char *name, const char *sig);
jfieldID (JNICALL *GetStaticFieldID)
(JNIEnv *env, jclass clazz, const char *name, const char *sig);

这两个函数中第一个参数为JNI环境;clazz为类的定义;name为属性名称;第四个参数同样是为了表达属性的类型。前面我们使用javap工具获取类的详细定义的时候有这样两行:

public java.lang.String msg;
/*   Ljava/lang/String;   */

其中第二行注释的内容就是第四个参数要填的信息,这跟访问类方法时是相同的。

3.读取和设置属性值

有了属性的定义要访问属性值就很容易了。有几个方法用来读取和设置类的属性,它们是:Get<TYPE>Field、Set<TYPE>Field、GetStatic<TYPE>Field、SetStatic<TYPE>Field。比如读取Demo类的msg属性就可以用GetObjectField,而访问COUNT用GetStaticIntField,相关代码如下:

jfieldID field = (*env)->GetFieldID(env,obj,"msg"," Ljava/lang/String;");
jstring msg = (*env)-> GetObjectField(env, cls, field);	//msg就是对应Demo的msg
jfieldID field2 = (*env)->GetStaticFieldID(env,obj,"COUNT","I");
jint count = (*env)->GetStaticIntField(env,cls,field2);

访问构造函数

很多人刚刚接触JNI的时候往往会在这一节遇到问题,查遍了整个jni.h看到这样一个函数NewObject,它应该是可以用来访问类的构造函数。但是该函数需要提供构造函数的方法定义,其类型是jmethodID。从前面的内容我们知道要获取方法的定义首先要知道方法的名称,但是构造函数的名称怎么来填写呢?其实访问构造函数与访问一个普通的类方法大体上是一样的,惟一不同的只是方法名称不同及方法调用时不同而已。访问类的构造函数时方法名必须填写“<init>”。下面的代码演示如何构造一个Demo类的实例:

jclass cls = (*env)->FindClass(env, "jni/test/Demo");
/** 
 首先通过类的名称获取类的定义,相当于Java中的Class.forName方法
*/
if (cls == 0) 
<error handler>
jmethodID mid = (*env)->GetMethodID(env,cls,"<init>","(Ljava/lang/String;)V ");
if(mid == 0)
<error handler>
jobject demo = jenv->NewObject(cls,mid,0);
/**
 访问构造函数必须使用NewObject的函数来调用前面获取的构造函数的定义
 上面的代码我们构造了一个Demo的实例并传一个空串null
*/

数组处理

创建一个新数组

要创建一个数组,我们首先应该知道数组元素的类型及数组长度。JNI定义了一批数组的类型j<TYPE>Array及数组操作的函数New<TYPE>Array,其中<TYPE>就是数组中元素的类型。例如,要创建一个大小为10并且每个位置值分别为1-10的整数数组,编写代码如下:

int i = 1;
jintArray array;	//定义数组对象
(*env)-> NewIntArray(env, 10);
for(; i<= 10; i++) 
(*env)->SetIntArrayRegion(env, array, i-1, 1, &i);

访问数组中的数据

访问数组首先应该知道数组的长度及元素的类型。现在我们把创建的数组中的每个元素值打印出来,代码如下:

int i;
/* 获取数组对象的元素个数 */
int len = (*env)->GetArrayLength(env, array);
/* 获取数组中的所有元素 */
jint* elems = (*env)-> GetIntArrayElements(env, array, 0);
for(i=0; i< len; i++)
printf("ELEMENT %d IS %d\n", i, elems[i]);

<<上一页 1 2 3 下一页>>


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· Eclipse使用入门 (02-13) · Java图形界面开发:SWT全接触 (02-12)
· EJB最佳实践:实体bean保护 (01-24) · Servlet/JSP服务器端的重定向 (01-24)
· Nokia推出Linux平台的手机软件开发工具 (01-22) · .NET不会是Java杀手 (01-21)
· 利用JAVA操作EXCEL文件 (01-21) · Java设计模式之复合模式篇 (01-21)
· 法院判微软120天内向用户提供新版JAVA (01-17) · 在Java2环境中应用IP地址封装对象 (01-17)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
资讯 通信 IT产品 IT技术 信息化
2009第七届中国电脑商年会直播
·创业投资系列访谈:产业..
·特别策划:视频网站系列..
·专题:网游虚拟货币新规..
专题:6月上市手机新品回顾及7月新机展望
·2009年中国电信业信息化..
·专题:把iPhone 3GS“解..
·WAPI重启国际标准进程 ..
专题:09年中盘点-联想春季打印机新品回顾
·InfoComm 2009 视听与集..
·网游背后的故事 网游服..
·[专题]联想ThinkPad T40..
BizSpark:微软为技术创业企业点燃火花
·社区活动:我的IT求知生..
·访谈:内网安全2009系列..
·安全访谈:网银安全之Sa..