使用NDK移植开源项目,JNI的使用技巧

PSINS工具箱15状态组合导航仿真程序(test_SINS_GPS_153)浅析-卡尔曼滤波设置+导航解算 文章目录test_SINS_GPS_153源码poserrsetkfinitgabiaskfupdate流程 test_SINS_GPS_153源码 poserrset function poserr = poserrset(dpos0, dlon, dhgt) % position errors dpos=[dlat;dlon;dhgt] setting. % % Prototype: poserr = poserrset(dpos0) % Input: dpos0=[dlat; dlon; dhgt], 阅读详情

使用NDK移植开源项目,JNI的使用技巧

2012-02-07 09:58 by Terry_龙, 4981 阅读, 2 评论, 收藏, 编辑

 

 jni 的介绍

 JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。以下介绍Android 中如何使用jni移植开源库的技巧.

 JNI日志输出到Logcat中

#include <android/log.h>
#define LOG_TAG "===xcloud==="
#define LOGI(...)  android_log_print(ANDROID_LOG_INFO,LOG_TAG,VA_ARGS__)
#define LOGW(...)  android_log_print(ANDROID_LOG_WARN,LOG_TAG,VA_ARGS__)
#define LOGE(...)  android_log_print(ANDROID_LOG_ERROR,LOG_TAG,VA_ARGS__)

 

Android.mk文件添加编译模块:
LOCAL_LDLIBS=-lm -llog
使用方法:
LOGE("%s",test);

JNI调用Java方法

以调用String 的getBytes方法为例:
第一步:
jclass clsstring = (*env)->FindClass(env,"java/lang/String"); //找到Java String 类
第二步:
jstring strencode = (*env)->NewStringUTF(env,"utf-8");  //得到一个jstring 对象
第三步:
jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B"); //得到getBytes方法

 

第四步:
jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr, mid, strencode); //“jstr 为传入的字符串”调用getBytes方法

第五步:
jsize alen = (*env)->GetArrayLength(env,barr); //得到数组长度

 

jstring 转换 char*

char* test=(char*)(*env)->GetStringUTFChars(env,jstringVariable,NULL);

 

 

返回一个java对象数组

第一步:
jclass objectClass=(*env)->FindClass(env,"com/xuzhitech/xcloud/resource"); //找到对应的java 类(对象)
第二步:
jobjectArray array=(*env)->NewObjectArray(env,currentListCount,objectClass,NULL); //通过取到的java类(对象)创建一个指定固定大小的数组
第三步:
jfieldID _uri=(*env)->GetFieldID(env,objectClass,"uri","Ljava/lang/String;");//找到对象中的列
注意:在JNI中并未提供jstring 类型的对象,所以必须通过L指定包名找到该类,在有提供的类型中,可以直接使用该类型的大写首字母(jlong 需使用J)
如jint 类型可以如此编写:
jfieldID _vcr=(*env)->GetFieldID(env,objectClass,"is_vcr","I");对应的JNI提供类型可以参考如下  http://download.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html
第四步:
jmethodID jid = (*env)->GetMethodID(env,objectClass,"<init>","()V");//"<init>"代表可以访问默认构造函数
jobject jobj=(*env)->NewObject(env,objectClass,jid); //通过第一步找到的jclass创建对应的对象

 

第五步:
(*env)->SetObjectField(env,jobj,_modtime,jmodtime); //为对象中的每一列赋值。注意:如果JNI有提供的数据类型,可按提供的类型为对象中的列赋值,
如:(*env)->SetIntField(env,jobj,_vcr,current->is_vcr);
第六步:
(*env)->SetObjectArrayElement(env,array,i,jobj);将对象设置进第二步声明的数组中
DeleteLocalRef(env,jobj);//删除引用对象

在JNI中循环读取对象数组

 

复制代码
for (i =  0 ;i < currentListCount ;i++) {
jobject obj = (*env)->GetObjectArrayElement(env,array,i);
jstring jstr=(*env)->GetObjectField(env,obj,_uri);
LOGE( " =====uri===%s==== ",jstringtoChar(env,jstr));
}
上面使用到的jstringtoChar方法代码:
/* *
*jstring to char
*/
char* jstringtoChar(JNIEnv* env,jstring jstr){
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, " java/lang/String ");
jstring strencode = (*env)->NewStringUTF(env, " utf-8 ");
jmethodID mid = (*env)->GetMethodID(env,clsstring,  " getBytes ",  " (Ljava/lang/String;)[B ");
jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr, mid, strencode);
jsize alen = (*env)->GetArrayLength(env,barr);
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;
复制代码

} 

 

cpp JNI与 c JNI的主要注意事项:

用C编写jni文件,访问JNI内置提供方法格式:
(*env)->SetObjectArrayElement(env,array,i,jobj);
用CPP编写JNI文件,访问JNI内置提供方法格式:
env->SetObjectArrayElement(array,i,jobj);
另外,使用CPP编写的JNI代码,在调用C语言编写的库的时候,要添加以下代码,才可以正常使用(不然在链接的时候找不到相关接口:undefined reference.....):
ifdef __cplusplus
extern "C" {
#endif
... //引入的头文件
#ifdef __cplusplus
}
#endif

 

其他用法几乎一致。

 

JNI 使用Native注册

按照上面的方法写函数体,必须遵循JNI官方的一大堆标准进行方法的定义,有时候方法一多,不大好管理,也不利用查看,并且每次都要写一大堆恶心的标准方法名也不是一件好事。对此JNI有一套可以通过Native 注册的机制可以使用,以方便函数体的编写。

 

以下是Android 调用JNI注册Natives 的步骤:
第一步
声明Java中要调用jni 的类路径:
static const char *className="com/xuzhitech/xcloud/cadaver";
第二步
创建方法格式结构体:
struct JNINativeMethod {
const char* name;//method name 
const char* signature; //java method return value 
void* fnPtr;//c/c++ method 
} ;

第三步
使用结构体注册需要供Android 调用的方法体:

复制代码
static JNINativeMethod methods[] = {
{ " StringTestOne ",  " ()Ljava/lang/String; ", ( void*)StringTestOne},
{ " executels ", " ()[Lcom/xuzhitech/xcloud/resource; ",( void*)executels},
{ " getProgress ", " ()Lcom/xuzhitech/xcloud/fileProgress; ",( void*)getProgress},
{ " getdownloadState ", " ()I ",( void*)getdownloadState},
{ " changeExecutable ", " (Ljava/lang/String;Ljava/lang/String;)I ",( void*)changeExecutable},
{ " Login ", " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I ",( void*)Login},
{ " getCurrentListCount ", " ()I ",( void*)getCurrentListCount},
{ " mkcol ", " (Ljava/lang/String;)I ",( void*)mkcol},
{ " deleteFile ", " (Ljava/lang/String;)I ",( void*)deleteFile},
{ " deleteCol ", " (Ljava/lang/String;)I ",( void*)deleteCol},
{ " getFullUri ", " ()Ljava/lang/String; ",( void*)getFullUri},
{ " cdCommand ", " (Ljava/lang/String;)I ",( void*)cdCommand},
{ " logout ", " ()V ",( void*)logout},
{ " doCopy ", " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I ",( void*)doCopy},
{ " doMove ", " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I ",( void*)doMove},
{ " getFile ", " (Ljava/lang/String;Ljava/lang/String;)V ",( void*)getFile},
{ " putFile ", " (Ljava/lang/String;Ljava/lang/String;)V ",( void*)putFile},
{ " lock ", " (Ljava/lang/String;)I ",( void*) lock},
{ " unlock ", " (Ljava/lang/String;Ljava/lang/String;)I ",( void*)unlock},
{ " getToken ", " (Ljava/lang/String;)Ljava/lang/String; ",( void*)getToken},
{ " isSetToken ", " (Ljava/lang/String;)I ",( void*)isSetToken},
复制代码

}; 

第一个参数为:Java实现要调用的方法名称
第二个参数为:该方法需要的返回值与方法参数,如->(方法参数)返回值,详细使用参考如下:
具体的每一个字符的对应关系如下

字符 Java类型 C类型

复制代码
V  void  void
Z jboolean boolean
I jint  int
J jlong  long
D jdouble  double
F jfloat  float
B jbyte  byte
C jchar  char
S jshort  short
复制代码

 

数组则以"["开始,用两个字符表示

复制代码
[I jintArray  int[]
[F jfloatArray  float[]
[B jbyteArray  byte[]
[C jcharArray  char[]
[S jshortArray  short[]
[D jdoubleArray  double[]
[J jlongArray  long[]
[Z jbooleanArray boolean[]
复制代码
也可返回任意java对象,如上代码的()[Lcom/xuzhitech/xcloud/resource;代表一个不带参数的方法,并且返回java类中的Lcom/xuzhitech/xcloud/resource;数组。'['代表数组的意思,'L'代表类的意思

 

第三个参数为,第一个参数需要映射的本地c/c++对应的函数指针方法。

第四步
在加载jni的时候指定JNI版本并且通过传入进来的class路径注册Natives 方法

 

复制代码
jint JNI_OnLoad(JavaVM* vm,  void * reserved){ 

jint result = JNI_ERR;
JNIEnv* env = NULL;
jclass clazz;
int methodsLenght;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
return JNI_ERR;
}
// assert(env != NULL); 
clazz = (*env)->FindClass(env,className);
if (clazz == NULL) {
LOGE("Native registration unable to find class '%s'", className);
return JNI_ERR;
}
methodsLenght = sizeof(methods) / sizeof(methods[0]);
if ((*env)->RegisterNatives(env,clazz, methods, methodsLenght) < 0) {
LOGE("RegisterNatives failed for '%s'", className);
return JNI_ERR;
}
// 
result = JNI_VERSION_1_4;
return result;
}

复制代码

 

 

注意,使用Natives注册运行程序时,它会先检测jni与java类使用jni 类的native 方法是否相对应与一致,即使你没有使用到该 方法也会进行检测。
第五步
通过上面的修改,c/c++编写的jni 文件就可以不带一大串标准名称了,您可以像正常编写c一样编写你的jni函数,如下:

复制代码
/*
*move file
*/
jint doMove(JNIEnv* env,jobject thiz,jstring jsrc,jstring jdest,jstring jrename){
char* src=( char*)(*env)->GetStringUTFChars(env,jsrc,NULL);
char* dest=( char*)(*env)->GetStringUTFChars(env,jdest,NULL);
char* rename=( char*)(*env)->GetStringUTFChars(env,jrename,NULL);
int returnValue=multi_move(src,dest,rename);
//  free(src);
(*env)->ReleaseStringUTFChars(env,jsrc,src);
//  free(dest);
(*env)->ReleaseStringUTFChars(env,jdest,dest);
//  free(rename);
(*env)->ReleaseStringUTFChars(env,jrename,rename);
return returnValue;
}
复制代码

 注:

JNI的一些基本方法的使用都可以参考这个网站:http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html

转自:http://www.cnblogs.com/TerryBlog/archive/2012/02/07/2340902.html

光储微电网混合储能系统的控制策略 随着社会生产力的不断提高,对不可再生资源的大量消耗,人们已经意识到发展可再生能源的重要性,因此微电网技术作为再生能源利用的有效形式被快速发展。蓄电池容量无限大是传统光储微电网混合储能系统控制策略一种理想形式,但实际上蓄电池的容量是有限度的,传统控制策略在蓄电池剩余电量达到阖值时将无法正常使用,由此提出了光储微电网混合储能系统的新型控制策略,又结合实际情况,对开关进行了改进,利用开关与二极管并联,使其拥有四种工作状态,当储能元件剩余电量达到阈值时,可自动恢复电量降低成本,提高并输出电池电能质量。 阅读详情

相关推荐

stc8g1k08硬件iic读取aht20温湿度及0.91寸oled显示

使用stc8g1k08读取aht20温湿度及0.91寸oled显示。

qq_61688416的博客 2771

Android Jni Native线程回调Java函数,env->findClass()失败。

Android Jni Native线程回调Java函数,env->findClass()失败。

lsg_lsg_lsg的博客 1470

《Ventoy 制作系统安装 U 盘的具体步骤》

然后您可以在电脑的磁盘管理中对 U 盘进行快速格式化,选择 FAT32 或 NTFS 文件系统。至此,Ventoy 系统安装 U 盘就制作完成了。您可以在需要安装系统的电脑上,从 U 盘启动,然后选择相应的系统镜像进行安装。安装完成后,将您需要的操作系统镜像文件(如 Windows、Linux 等的 ISO 格式镜像)复制到 U 盘的根目录。在安装程序中,选择您插入的 U 盘设备,确保选择正确,以免误操作。2. 确认选择的 U 盘盘符正确,防止误操作导致其他磁盘数据丢失。点击“安装”按钮,等待安装完成。

jiyiwangluokeji的博客 2668

JNI学习积累之三 ---- 操作JNI函数以及复杂对象传递

本文原创,转载请注明出处:http://blog.youkuaiyun.com/qinjuning          在掌握了JNI函数的使用和相关类型的映射后,以及知晓何利用javah工具生成对应的jni函数以及如何生成动态     链接库 (windos下就是.dll库,Linux就是.so库了,不懂在Window下生成dll动态库的,具体流程可看我的这篇博

SweetLoveFT的专栏 688

成分数据的闭合效应对地球化学数据的影响及其解决方案

封闭效应 (Closure Effect),也称为常数和效应 (Constant Sum Effect),是地球化学数据分析中一个需要特别注意的统计现象。它的产生是由于我们通常使用成分数据 (Compositional Data)百分比 (%)百万分率 (ppm)由于这些数据表示的是各组分占总体的比例,它们的总和必然是一个常数 (例如 100% 或 1,000,000 ppm)。这意味着每个元素的含量不是独立的,而是与其他元素的含量相互制约。改变其中一个元素的含量必然会影响其他元素的相对比例。

qq_59349063的博客 1535

告别死记硬背!用业务场景驱动理解SAP PS OPSA参数文件配置

本文通过制造业新产品研发项目案例,详细解析SAP PS模块中OPSA参数文件配置的实际应用。从项目立项、WBS分解到研发物料管理,系统讲解关键配置项的业务价值,帮助用户告别死记硬背,实现业务场景驱动的参数配置学习。特别适合制造业项目管理人员提升SAP PS配置效率。

weixin_30415113的博客 481

JNI之C语言(三)-- 基本语法

3. 基本语法 变量 全局变量 定义在函数之外的变量 对所有的函数都可见 在程序运行过程一直存在并可用 局部变量 定义在函数内部的变量 只在所在的函数内可见, 其它函数不能使用 一般的局部变量当函数执行完后自动释放 运算符 定义 用来在内存中进行特定运算的符号 分类 基本运算符 其它运算符 补充 表达式 语句 定义 分类 简单语句 声明语句 int i

新火燎塬的博客 807

STM32CubeIDE无法连接STLinkV2的一个可能原因

前些日子买了个新的STLINKV2 , ( 老的被我家猫猫一泡尿送上西天了)刚开始还挺正常的, 后来有一天就突然间发现无法调试了.网上尝试了各种方法, 各种操作. 百度了好久. 最后好在我自己研究出来了.我使用的是 STM32CubeIDE 这个开发工具调试选项如下图其它的不需要修改, 然后点击下面的apply 按钮, 然后调试Debug, 提示 No STLink 如下图后来尝试了下载ST-LINK Utility 用它是可以正常连接STLink的, 然后也能正常进行升级操作.

走错路的程序员 9828

VSAN缓存盘故障处理:从RAID0模式到磁盘组重建

在分布式存储和虚拟化环境中,RAID0常被视为高风险的数据组织方式——因为条带化没有冗余,任何一块盘损坏都会导致整个逻辑卷不可用。VMware VSAN中的缓存盘(Cache盘)在磁盘组里扮演着类似的角色:它既是读缓存又是写缓冲,但同时缺乏独立冗余,一旦故障,整个磁盘组会进入降级状态,甚至引发数据重建风暴。理解缓存盘与容量盘的分工,以及RAID0、RAID1、RAID5与VSAN的FTT策略之间的关系,是高效运维的基础。本文从VSAN存储架构出发,梳理缓存盘故障的排查链路,包括vCenter健康检查、ESX

weixin_34323858的博客 261

零差云控 ZeroErr eRob 电机 CAN、CANopen、EtherCAT、ROS2 机器人开发详细教程

TwinCAT 3(Windows 控制与自动化技术)是 Beckhoff 提供的开发平台,可将任何兼容 PC 转变为实时控制系统,用于管理各种类型的工业自动化系统,如 PLC(可编程逻辑控制器)、运动控制、机器人等。

机器人控制与仿真应用 1万+

硬方案——几种实用的恒流源电路设计方案,敬请收藏(运放、三极管在手,让你玩出多种花样)

0 引言 我们在信号测量、供电等应用场景时常会涉及到使用恒流源,以前觉得恒流源挺神奇的,研究了下实现方案,其实也没有多么高深(这里讨论的仅限于用在信号测量中的小电流恒流源设计),这里给出几个实用的恒流源电路设计方案。 1 恒流源电路设计 (1)使用三极管搭建的恒流源 (2)使用运放搭建的恒流源 (3)使用恒流二极管搭建的恒流源 pt100恒流源测温电路图_电子技术_电工之家 ...

数字世界 万物互联 9524

【原理+实战+视频+源码】抖音,快手大热背后——Android-贴心的音视频学习指南来咯

最后这里放上我这段时间复习的资料,这个资料也是偶然一位朋友分享给我的,里面包含了腾讯、字节跳动、阿里、百度2020-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。还有高级架构技术进阶脑图、高级进阶架构资料帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。一起互勉~《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

m0_67392182的博客 938

PostgreSQL 核心原理:大字段(大对象)是如何被压缩和存储的(TOAST存储机制)

PostgreSQL通过TOAST机制高效处理大字段存储问题,解决单行超过8KB页大小限制的挑战。TOAST采用透明分片、按需加载和自动压缩策略,支持TEXT、JSONB等变长类型,无需用户干预。其核心包括四种存储策略(plain/external/main/extended),自动将大字段分片存入专用TOAST表,主表仅保留指针。读取时按需解压拼接,支持部分加载优化。TOAST表结构包含chunk_id、序列号和分片数据,配合内置PGLZ压缩算法,平衡存储效率与访问性能。该机制使PostgreSQL能稳定

数据知道的博客 2625

Android JNI(一)——NDK与JNI基础

Java调用C/C++在Java语言里面本来就有的,并非Android自创的,即JNI。JNI就是Java调用C++的规范。当然,一般的Java程序使用的JNI标准可能和android不一样,Android的JNI更简单。

hirezy 3306

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

JNI/NDK入门指南之正确姿势了解JNI和NDK

         你真的了解Android中JNI/NDK吗?    随着Android生态的发展,越来越多的行业开始使用Android操作系统,这就造就了对Android设备的应用性能和安全要求越来越高,随之而来的对JNI/NDK开发的需求也越来越大。虽然网上或者很多书籍都有关于此方面的讲解,但是都是上来直奔主题说怎么使用JNI/NDK,而没有将啥是JNI和NDK讲解清楚。所以导致很...

IT先森 3569

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

[NDK/JNI系列01] NDK与JNI的基本概念与使用场景

介绍是NDK和JNI,它们有什么作用和优势 使用场景和案例 , Android系统服务与JNI的通讯

我其实什么都不会 6768

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: Android Fragments 详细使用
下一篇: JVM内存模型及垃圾回收机制
HabbyGe
博客等级 码龄16年 46粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值