博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jni c++
阅读量:5905 次
发布时间:2019-06-19

本文共 2931 字,大约阅读时间需要 9 分钟。

   
   
    上述两篇文章对jni的讲解比较详细,各有利弊,就文章1来说,开门见山,直接阐述了java和C/C++的交互方式;文章2是一篇百度文库中的内容,则讲的比较详细,从各个方面阐述了jni到底是个怎么一回事,很适合初学者看。
    JNI是Java Native Interface的缩写,它是java平台的一部分,允许Java代码和其他语言写的代码进行交互。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境下。
    在写这篇文章的时候,虽然技术不怎么好,但却是一个实打实的C++程序员,因此在这篇文章中有关java的内容可能表述的不是那么准确。
    说到jni,个人觉得有这么一句话说的比较好:只有当你必须在同一进程中调用本地代码时,再使用JNI。为什么这么说,原因很简单,文章开头已经说过了,为什么要写这么文章,原因更加明确了,项目需要,不使用不行。
    废话不多说,接下来我就讲述下我个人使用jni时的一些理解和觉着比较重要的地方,在讲解jni时,我从以下方面讲解:头文件生成、类型转换、java代码通过jni调用C++和C++通过jni调用java,至于java怎么加载jni动态库我就不在文章中描述了,毕竟java不太懂。
   
头文件生成
    编写带有native声明的方法的java类,使用javac命令编译所编写的java类,然后使用javah + java类名生成扩展名为h的头文件
    public native void displayHelloWorld();//所有native关键词修饰的都是对本地的声明
    JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv*,jobject);//生成的jni层头文件,在此详细解释下这个函数声明的意思,JNIEXPORT:导出函数、void:U返回值、JNICALL:jni调用接口、Java:java语言、HelloWorld:方法所述类、displayHelloWorld:方法名称、JNIEnv*指针指向一个函数指针表,在VC中可以直接用"->"操作符访问其中的函数、 jobject 指向在此 Java 代码中实例化的 Java 对象 LocalFunction的一个句柄,相当于this指针
   
类型转换
    说到类型转换,由于作者在使用jni的过程中,jni方法的参数都是json的字符串类型传递,因此网上传递数组的方式我就不多解释了,反正用的也不多
   
首先我说下jstring转换为char *,为了方便使用,我们可以自定义类,把这两个方法分别封装在类的构造函数和析构函数中
const char* GetStringUTFChars (jstring string,jboolean* isCopy)
    返回指向字符串UTF编码的指针,如果不能创建这个字符数组,返回null。这个指针在调用ReleaseStringUTFChar()函数之前一直有效。 参数:string Java字符串对象,isCopy 如果进行拷贝,指向以JNI_TRUE填充的jboolean,否则指向以JNI_FALSE填充的jboolean。
void ReleaseStringUTFChars(jstring str, const char* chars)
    通知虚拟机本地代码不再需要通过chars访问Java字符串。
    参数:string Java字符串对象,chars 由GetStringChars返回的指针
   
下边是char * 转换为jstring,为了方便起见还是封装成类来使用
jstring NewStringUTF(const char *utf)
    返回一个新的Java字符串并将utf内容拷贝入新串,如果不能创建字符串对象,返回null。通常在反值类型为string型时用到。
    参数:utf UTF编码的字符串指针,对于数值型参数,在C/C++中可直接使用void DeleteLocalRef(jstring str)释放jstring串和本地字符串的关联关系。
   
java代码通过jni调用C++
    java写的native方法调用时对应的就调用了jni层的方法,然后我们只需要实现jni的方法时,调用我们自己的C++嗲吗,就实现了java掉C++。
   
C++通过jni调用java
jmethodID:保存java方法ID的数组,获取方法下文有讲解
CallVoidMethod:JNIEnv *方法,参数1:jobject对象,由jni层传入,并暂时保存在jni层、参数2:java方法ID、后边一次是被调用方法的参数
JavaVM::AttachCurrentThread:附加到当前线程
JavaVM::DetachCurrentThread:从当前线程脱离
JNIEnv *pEnv;    global_vm->GetEnv((void**)&pEnv, JNI_VERSION_1_6);    bool isAttached = false;    if (pEnv == NULL)    {        int status = global_vm->AttachCurrentThread(&pEnv, NULL);        if (status < 0)        {            return;        }        isAttached = true;    }    JniString *jsSourceID = new JniString(pEnv, strGroupID.c_str());    pEnv->CallVoidMethod(m_pCallback, m_pMethodId[15], jsSourceID->getL(), nRet);    delete jsSourceID;    if (isAttached)        global_vm->DetachCurrentThread();
基于以上代码给出如下解释:
JniString:自己封装的类,把char *变量封装成jstring类型变量
jobject m_pCallback = pEnv->NewGlobalRef(pCallback);//pCallback为jObject,由java代码引入,jni层注册到此jclass m_pClass  =  (jclass)pEnv->NewGlobalRef( pEnv->GetObjectClass(m_pCallback));m_pMethodId[15] = pEnv->GetMethodID(m_pClass, "OnUpdateGroupSite", "(Ljava/lang/String;I)V");
至此,java和C++的相互调用就基本讲完了,如果有什么不对的地方或者不理解的地方,欢迎大家留言反问!!!
jni <wbr>c++
jni <wbr>c++

转载地址:http://xacpx.baihongyu.com/

你可能感兴趣的文章
Linux有问必答:如何在 Ubuntu 15.04 的 GNOME 终端中开启多个标签
查看>>
CentOS 下安装 LEMP 服务(nginx、MariaDB/MySQL 和 php)
查看>>
ROS机器人程序设计(原书第2版)2.1 理解ROS文件系统级
查看>>
v聊聊 Swift 3.0 - 新版本对我们的影响
查看>>
Ubuntu Builder —— 一个制作自己的发行版的工具
查看>>
myeclipse构建MAVEN
查看>>
Android应用框架之BroadcastReceiver
查看>>
java.util.concurrent.ConcurrentSkipListSet 基于跳跃链表的并发set
查看>>
PostgreSQL 10.0 preview 多核并行增强 - 索引扫描、子查询、VACUUM、fdw/csp钩子
查看>>
nlp文本处理开源工具,及聊天机器人实现
查看>>
云效有约|从CTO视角出发,技术资源都去哪儿了?
查看>>
双11技术攻略:企业云架构的正确姿势
查看>>
【云栖大会】再谈开源大数据
查看>>
Sublime秘籍,一般人我不告诉他
查看>>
【ANDROID游戏开发十三】(保存游戏数据 [下文])详解SQLITE存储方式,并把SQLITE的数据库文件存储在SD卡中!!!...
查看>>
INPUT链为DROP时,如何才能正常连接外部网络?
查看>>
windows无法访问vmware搭建好虚拟机linux web服务器
查看>>
空中网多线程面试题
查看>>
python __setattr__, __getattr__, __delattr__, __call__
查看>>
Understanding the CVS Structure
查看>>