java jni 参数_Jni接口-深入研究参数的传递(一)

本文深入探讨Java与C++之间的JNI参数传递,解释JNIEXPORT、JNIEnv、jobject等概念,并通过示例展示如何在C++.net中改变Java变量值。内容包括JNI接口方法的声明、数据类型对应及变量的读写操作。
摘要由CSDN通过智能技术生成

在上一个随笔中介绍了怎样实现一个简单的Jni小程序。在这一篇里主要是说一下JAVA与C++之间的参数传递问题。

本人是个Java程序员,工作没几年  菜鸟级别,C++不是很熟悉,但对.NET到是了解一些,所以这里面的C++部分都用C++.net来讲的。为了便于理解,文档中可能会有很多通俗易懂的白话,最近也是项目中用到了Jni 才学习了几天,所以这里要是有哪说得不对,还请大家见谅,发现问题就指出来,大家一起学习 哈!

先大致回顾下上一篇的内容,在上一篇里我们创建了一个JAVA类Test.java和C++.net的Jin01项目。主要是实现Jin01中输出“第一个Jni小程序”,然后用Test.java来调用。(详情请见上一篇内容)

Jni01中的函数是:

#include "stdafx.h"

#include "WINSCARD.H"

#include "com_test01_Test.h"

using namespace System;

int main(array<:string> ^args) {

Console::WriteLine(L"Hello World");

return 0;

}

//实现Java_com_test01_Test_firstTest方法

JNIEXPORT void JNICALL Java_com_test01_Test_firstTest(JNIEnv *, jobject){

Console::WriteLine(L"第一个Jni小程序");

}

Test.java代码如下:

public class Test {

public native void firstTest();//

public static void main(String[] args) {

System.loadLibrary("Jni01");

Test t=new Test();

t.firstTest();

}

}

1、com_test01_Test.h头文件中实现Jni接口方法深入研究

在上一篇的例子中实现Jni接口的方法声明在com_test01_Test.h头文件中,代码如下:(以下按照字体颜色来解释每个部分的意思)

JNIEXPORT void JNICALL Java_com_test01_Test_firstTest   (JNIEnv * env, jobject obj);

(1)JNIEXPORT :在Jni编程中所有本地语言实现Jni接口的方法前面都有一个"JNIEXPORT",这个可以看做是Jni的一个标志,至今为止没发现它有什么特殊的用处。

(2)void :这个学过编程的人都知道,当然是方法的返回值了。

(3)JNICALL :这个可以理解为Jni 和Call两个部分,和起来的意思就是 Jni调用XXX(后面的XXX就是JAVA的方法名)。

(4)Java_com_test01_Test_firstTest:这个就是被上一步中被调用的部分,也就是Java中的native 方法名,这里起名字的方式比较特别,是:包名+类名+方法名。

(5)JNIEnv * env:这个env可以看做是Jni接口本身的一个对象,在上一篇中提到的jni.h头文件中存在着大量被封装好的函数,这些函数也是Jni编程中经常被使用到的,要想调用这些函数就需要使用JNIEnv这个对象。例如:env->GetObjectClass()。(详情请查看jni.h)

(6)jobject obj:刚才在Test类的main方法中有这样一段代码:

Test t=new Test(); t.firstTest();

这个jobject需要两种情况分析。上段代码中firstTest方法是一个非静态方法,在Java中要想调用它必须先实例化对象,然后再用对象调用它,那这个时候jobject就可以看做Java类的一个实例化对象,也就是obj就是t。如果firstTest是一个静态方法,那么在Java中,它不是属于一个对象的,而是属于一个类的,Java中用Test.firstTest()这样的方式来调用,这个时候jobject就可以看做是java类的本身,也就是obj就是Test.class。

2、Jni中的数据类型

每一个Java的数据类型在Jni中都一个和它相对应的数据库类型,这样才能保证Java调用C或者C++的过程中数据的正确性。

打开Jni.h文件,有如下代码:

3784d83f0af6b3367916d04b4aec80aa.png

这里声明了所有Jni支持的数据类型,可以发现一个规律所有Jni的数据类型前面都有一个”J“字母,这样主要是为了好记。在Java中所有的对象都以引用的形式体现的,为了保持一致 所以在C与C++中使用了指针类型。Java与Jni中数据类型的对照表如下:

3cfab8139dbabdfa9968716e7fea8364.png

3、实例:在C++.net程序中改变Java中变量的值

在原有Test.java中声明一个整形变量message,如下:

public class Test {

public native void firstTest();//第一个Jni

public int message;

public static void main(String[] args) {

System.loadLibrary("Jni01");

new Test().firstTest();

}

}

在Jni01的 Java_com_test01_Test_firstTest方法中写如下代码:

JNIEXPORT void JNICALL Java_com_test01_Test_firstTest(JNIEnv * env, jobject obj){

jclass class_Test=env->GetObjectClass(obj);    //注释(1)

jfieldID fid_msg=env->GetFieldID(class_Test,"message","I");//注释(2)

env->SetIntField(obj,fid_msg,123);//注释(3)

}

(1)调用GetObjectClass方法来获取Jclass,GetObjectClass的参数就是obj

(2)调用GetFieldID方法来获取jfieldID,这里要说明一下Jni的所有操作,其实就是操作方法或者是操作属性两种。操作方法时需要根据方法的ID(jmethodID)来操作,可以理解为jmethodID标识了这个方法,也就是通过这个jmethodID可以找到你要找的方法。同理操作属性时也要根据该属性的ID(jfieldID )来操作。上面那段代码里我们要改变 变量message的值,所以要先获取该变量的jfieldID 。获取变量的jfieldID 方法是GetFieldID。GetFieldID需要3个参数。第一个是上一步获取的Jclass,第二个参数是Java中的变量名,最后一个参数是变量签名(int 的变量签名是”I“)。

下面是所有Jni中的变量签名列表:

b5ae7daf4405e0966ba533cf0c7c01bc.png

(3)最后调用SetIntField方法就可以设置变量 message的值了。在JAVA的测试环境中打印一下变量的值就知道是否成功了。

全部完成后,可以自己试验下使用GetIntField方法将message的值取出来。对于这些Jni.h中的方法就不过多的说了,自己看就应该能会用。在以后的随笔里会多说一些数据转换的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值