JNI内两种方式从C/C++中传递一维、二维、三维数组数据至Java层详细梳理
创始人
2024-05-29 21:40:59
0

目录

0 前言

1 准备工作介绍

2 一维数组

2.1 return形式

2.2 参数形式

3 二维数组

3.1 return形式

3.2 参数形式

4 三维数组

4.1 return形式

4.2 参数形式

5 测试代码

6 结果说明


0 前言

        就如之前我写过的一篇文章【JNI内形参从C代码中获取返回值并返回到Java层使用】中所描述的一样,JNI编程往往需要考虑的就是如何将C/C++中计算分析得到的数据传递至Java层。传递的方式就有两种:①直接通过函数return出来;②再就是通过形参获取得到。在以上文章内介绍了int值得传递情况,这篇文章则具体讲述数组得传递方式和操作,包括一维数组、二维数组以及三维数组,数组使用到三维基本满足了绝大部分的使用需求了。

        之所以写这篇文章,也是因为检索了很久对于数组在JNI内传递数据方式只看到第一种通过return方式传递的。为此就将自己工作整理出来,实现数组通过形参的方式传递数据给java层。

1 准备工作介绍

        在写测试案例之前需要有系列的准备工作,由于这不是重点,该部分我简单介绍一下。首先需要创建java工程,然后编写java文件,生成JNI头文件,最后编译成动态库。这里面具体可以参考:【IntelliJ IDEA平台下JNI编程(一)—HelloWorld篇_idea jni_走召大爷的博客-CSDN博客】

        本次编写环境Ubuntu18.04 、gcc7.5.0、生成.so动态库、IDEA平台。以下分别介绍在jni层不同维度数组不同形式传递数据的代码写法,具体介绍可以看代码内部注释。

2 一维数组

2.1 return形式

//一维数组  return形式向JAVA传递数据
JNIEXPORT jdoubleArray Java_com_test_java_JNItest_test0(JNIEnv *env, jobject)
{int n = 3;	//构造/模拟一个数组double test[3] = {0.0,1.0,2.0};//定义一维数组,数组元素个数为n=3jdoubleArray one = env->NewDoubleArray(n);env->SetDoubleArrayRegion(one,0,n,test);	return one;}

2.2 参数形式

//一维数组  形参向JAVA传递数据
JNIEXPORT jint Java_com_test_java_JNItest_test3
(JNIEnv *env, jobject,jdoubleArray result)
{int n = 3;//构造/模拟一个数组double test[3] = {0.0,1.0,2.0};env->SetDoubleArrayRegion(result,0,n,test);	return 0;	
}

3 二维数组

3.1 return形式

//二维数组  return形式向JAVA传递数据
JNIEXPORT jobjectArray Java_com_test_java_JNItest_test1(JNIEnv *env, jobject)
{//构造二维数组double test[2][3] = {{1.0,2.0,3.0},{3.0,3.0,6.0}};//一维数组  类型定义jclass ArrCls1 = env->FindClass("[D");  //创建一个有polygonpointNum个元素,每个元素的值是NULL的一维数组的数组  jobjectArray second = env->NewObjectArray(2, ArrCls1, NULL);  //等同二维数组//对于二维数组其内容是每一个一维数组,那么就循环定义一维数组,直接存入结果里面  //对于测试的二维数组:其为2x3固定的,不然通过下面循环可以获取变长的数组内容for(int i = 0;i < 2;i++){	int num = 3;//定义一维数组,数组元素个数为num=3jdoubleArray darr = env->NewDoubleArray(num);//将test的内容赋值给darrenv->SetDoubleArrayRegion(darr, 0, num, test[i]);//然后再将darr一维数组内容直接按顺序赋值给second二维数组env->SetObjectArrayElement(second, i, darr);  //删除临时元素darr数组  env->DeleteLocalRef(darr); }		return second;}

3.2 参数形式

//二维数组  形参向JAVA传递数据
JNIEXPORT jint Java_com_test_java_JNItest_test4(JNIEnv *env, jobject, jobjectArray  result)
{//构造二维数组double test[2][3] = {{1.0,2.0,3.0},{3.0,3.0,6.0}};//对于二维数组其内容是每一个一维数组,那么就循环定义一维数组,直接存入结果里面  //对于测试的二维数组:其为2x3固定的,不然通过下面循环可以获取变长的数组内容for(int i = 0;i < 2;i++){	int num = 3;//定义一维数组,数组元素个数为num=3jdoubleArray darr = env->NewDoubleArray(num);//将test的内容赋值给darrenv->SetDoubleArrayRegion(darr, 0, num, test[i]);//然后再将darr一维数组内容直接按顺序赋值给二维结果数组,如此就将c/c++内部的数组内容通过result传递到java层了env->SetObjectArrayElement(result, i, darr);  //删除临时元素darr数组  env->DeleteLocalRef(darr); }		return 0;}

4 三维数组

4.1 return形式

//三维数组  return形式向JAVA传递数据
JNIEXPORT jobjectArray Java_com_test_java_JNItest_test2(JNIEnv *env, jobject)
{//构造一个三维数组,示例为两个多边形,每个多边形3个顶点,每个顶点由x,y组成double test[2][3][2] = {{{1.0,2.0},{3.0,5.0},{2.0,4.0}},{{1.0,2.0},{3.0,5.0},{2.0,4.0}}};int polygonNum = 2;//二维数组类型定义jclass ArrCls2 = env->FindClass("[[D");          //实例化三维数组对象,第一个参数数据的大小,第二个参数用来实例化用的类是一个二维数组,也就是数组里的每个元素都是一个二维数组    	  jobjectArray three = env->NewObjectArray(polygonNum, ArrCls2, NULL);  //这样three就是一个三维数组。for(int i = 0;i < polygonNum;i++)  { int polygonpointNum =  3;//一维数组  类型定义jclass ArrCls1 = env->FindClass("[D");  //创建一个有polygonpointNum个元素,每个元素的值是NULL的一维数组的数组  jobjectArray second = env->NewObjectArray(polygonpointNum, ArrCls1, NULL);  //等同二维数组for (int j = 0; j < polygonpointNum; j++) {  jdouble tmp[2]; //构造每一个一维存储单元/* make sure it is large enough! */tmp[0] = test[i][j][0];  tmp[1] = test[i][j][1];    //也可以不构造和赋值,后面one的赋值可以env->SetDoubleArrayRegion(one, 0, 2, test[i][j]);也可以的 //定义有两个元素的一维数组jdoubleArray one = env->NewDoubleArray(2);  //把tmp里数据从0开始传递2个到one里 env->SetDoubleArrayRegion(one, 0, 2, tmp);  //给二维数组second的第j个元素设置值  env->SetObjectArrayElement(second, j, one);  //注意理解内容填充(数组初始化)//删除临时元素one数组  env->DeleteLocalRef(one);  }  //给三维数组里的第i个元素设置值,值是一个有一个元素组成的二维数据env->SetObjectArrayElement(three, i, second);  //删除临时元素二维数组  env->DeleteLocalRef(second);  } return three;
}

4.2 参数形式

//三维数组  形参向JAVA传递数据
JNIEXPORT jint Java_com_test_java_JNItest_test5(JNIEnv *env, jobject, jobjectArray  result)
{//构造一个三维数组,示例为两个多边形,每个多边形3个顶点,每个顶点由x,y组成double test[2][3][2] = {{{1.0,2.0},{3.0,5.0},{2.0,4.0}},{{1.0,2.0},{3.0,5.0},{2.0,4.0}}};int polygonNum = 2;for(int i = 0;i < polygonNum;i++)  { int polygonpointNum =  3;//一维数组  类型jclass arrClass = env->FindClass("[D");  //创建一个有polygonpointNum个元素,每个元素的值是NULL的一维数组的数组  jobjectArray second = env->NewObjectArray(polygonpointNum, arrClass, NULL);  //等同二维数组//给一维数据填充值  for (int j = 0; j < polygonpointNum; j++) {  jdouble tmp[2]; //构造每一个一维存储单元tmp[0] = test[i][j][0];  tmp[1] = test[i][j][1]; //也可以不构造和赋值,后面one的赋值可以env->SetDoubleArrayRegion(one, 0, 2, test[i][j]);也可以的//创建一个有2个元素的一维数组jdoubleArray one = env->NewDoubleArray(2);  //把tmp里数据从0开始传递2个到one里  env->SetDoubleArrayRegion(one, 0, 2, tmp);  //给二维数组second的第j个元素设置值  env->SetObjectArrayElement(second, j, one);  //注意理解内容填充(数组初始化)//删除临时元素one数组  env->DeleteLocalRef(one);  }  //给需要传出的三维数组里的每个元素设置值,值是一个有一个元素组成的二维数据env->SetObjectArrayElement(result, i, second);  //删除临时元素二维数组  env->DeleteLocalRef(second);  } return 0;}

5 测试代码

        在java内的测试代码如下:

package com.test.java;/*** @author yh* @version 1.0* @date 23-3-6 下午8:58*/
public class JNItest {static {System.load("/root/workspace-yh/javaProjectTest/jni/libjnitest.so");}public native double[] test0();public native double[][] test1();public native double[][][] test2();public native int test3(double[] result);public native int test4(double[][] result);public native int test5(double[][][] result);public void printOneArray(double[] t){int n = t.length;for(int i = 0;i < n;i++){System.out.println(t[i]);}}public void printSecondArray(double[][] t){int n = t.length;for(int i = 0;i < n;i++){int m = t[i].length;String temp = "";for(int j = 0;j < m;j++){temp += t[i][j]+",";}System.out.println(temp);}}public void printThreeArray(double[][][] t){int n = t.length;for(int i = 0;i < n;i++){int m = t[i].length;for(int j = 0;j < m;j++){String temp = "";int k = t[i][j].length;for(int l = 0;l < k;l++){temp += t[i][j][l]+",";}System.out.println(temp);}}}public  static void main(String[] args){JNItest JNI = new JNItest();double[] a3 = new double[3];double[][] a4 = new double[2][2];double[][][] a5 = new double[2][3][2];System.out.println("-------------------test0-----------------");double[] a0 = JNI.test0();JNI.printOneArray(a0);System.out.println("-------------------test3-----------------");int rnt3 = JNI.test3(a3);JNI.printOneArray(a3);System.out.println("-------------------test1-----------------");double[][]a1 = JNI.test1();JNI.printSecondArray(a1);System.out.println("-------------------test4-----------------");int rnt4 = JNI.test4(a4);JNI.printSecondArray(a4);System.out.println("-------------------test2-----------------");double[][][]a2 = JNI.test2();JNI.printThreeArray(a2);System.out.println("-------------------test5-----------------");int rnt5 = JNI.test5(a5);JNI.printThreeArray(a5);}    }

6 结果说明

        直接执行main函数,控制台打印信息:

         根据结果可以看到,两种方式均把c/c++层数据传递到了java层了。那么后面根据工程需要想怎么传递数据就怎么传递数据,想怎么使用接口就怎么设计接口了。

参考文章:

JNI 返回二维、三维,char、float、int、long型数组到java层_谢文浩博客-CSDN博客_jni 返回二维数组

Android Studio开发之JNI层开发 --- jni层返回二维数组对象_Jimmy-CSDN博客_jni 返回二维数组

android jni jobjectArray存储输出不同类型的数据_阿文的博客-CSDN博客_jni jobjectarray

相关内容

热门资讯

谷歌安卓系统开源免费用,免费体... 你知道吗?在科技的世界里,有时候最让人惊喜的就是那些免费又好用的东西。今天,就让我来给你揭秘一个超级...
安卓电脑版怎么装系统,轻松实现... 你有没有想过,你的安卓电脑版突然间卡得像蜗牛一样,慢得让人抓狂?别急,今天就来教你怎么给它来个焕然一...
安卓系统有几种语音,揭秘多样化... 你知道吗?安卓系统里的语音功能可真是让人爱不释手呢!想象你只需要动动嘴,就能完成各种操作,是不是觉得...
扫码系统推荐安卓游戏,畅享指尖... 你有没有发现,最近手机里的游戏推荐越来越贴心了?没错,就是那个神奇的扫码系统!今天,就让我带你一探究...
手机系统安卓做的最好,探索最佳... 你有没有发现,现在手机市场上,安卓系统简直是要风得风,要雨得雨,简直是手机系统中的佼佼者!不信?那就...
安卓系统越拉越难用,越拉越难用... 你有没有发现,最近安卓系统越来越难用了?是不是每次打开手机,都感觉卡得要命,各种广告弹窗让人头疼不已...
卓安系统创始人,引领科技浪潮的... 你有没有想过,在这个信息爆炸的时代,谁才是那个站在风口浪尖,引领科技潮流的先锋?今天,我要带你认识一...
安卓10系统经常断网,安卓10... 最近是不是你也遇到了安卓10系统经常断网的问题?这可真是让人头疼啊!手机断网,就像失去了方向感的指南...
开发安卓系统用什么,从工具到实... 你有没有想过,为什么你的手机里装了那么多应用,却还是觉得不够用呢?其实,这一切都离不开一个强大的操作...
安卓系统如何双开抖音,安卓系统... 如何在安卓系统上双开抖音:让你的娱乐生活更加丰富多彩在数字化时代,手机已经成为我们生活中不可或缺的一...
安卓8.0系统内测地址,探索系... 你有没有听说最近安卓8.0系统内测的消息?这可是科技圈的大事啊!作为一个紧跟潮流的数码爱好者,我可是...
安卓系统可以账号同步吗,安卓系... 你有没有想过,你的安卓手机里的各种账户信息,比如微信、QQ、支付宝,能不能像变魔术一样,一键同步到另...
安卓系统的平板怎么下载,畅享应... 你有没有想过,拥有一款安卓系统的平板电脑,那感觉简直就像拥有了整个世界?想象随时随地都能畅游网络海洋...
win平板上装安卓系统咋样,开... 亲爱的读者们,你是否曾想过在Windows平板上体验安卓系统的魅力?想象那双熟悉的Windows界面...
给安卓车机写系统,安卓车机系统... 你有没有想过,你的安卓车机系统其实可以焕然一新?想象当你驾驶着爱车,车机界面流畅得像丝滑的巧克力,功...
虚拟机和安卓系统,探索虚拟机与... 你有没有想过,为什么你的手机可以同时运行那么多应用,而且还能保持流畅呢?这背后可是有个大功臣——虚拟...
安卓系统小手表怎么用,享受智能... 你有没有发现,现在的小手表越来越智能了,尤其是安卓系统的小手表,功能强大到让人惊叹。想象手腕上一块小...
安卓系统为什么老是重启,安卓系... 手机突然重启,是不是又闹脾气了?安卓系统为什么老是重启,这个问题让不少小伙伴头疼不已。今天,就让我带...
米家苹果安卓系统,融合智能生活... 你知道吗?最近在智能家居圈子里,米家与苹果的合作可是引起了不小的轰动呢!咱们就来聊聊这个话题,看看米...
中国人不用安卓系统,为何中国人... 你知道吗?在这个科技飞速发展的时代,手机已经成为了我们生活中不可或缺的一部分。但是,你知道吗?有一群...