Linux java jni调用C++封装动态库

        由于项目中java需要调用第三方提供的C++动态库;由于第三方动态库传入的参数较多,还伴随着指针传入操作,导致java调用极为不便!因此催生出对于第三方的C++动态库进行二次封装。java调用只需按结构传入一个结构化的string即可。话不多说开干!

第三方库

        第三方C++的头文件HD10_safe.h如下:

#ifndef _HD10_safe_H_
#define _HD10_safe_H_#ifdef _cplusplus
extern "C" {
#endiftypedef	enum VKeyGenResultEx
{KGRE_OK 	,KGRE_NOT_OK
}KeyGenResult;typedef enum ECUS
{BCM=1, DCM, IC_6000, GW, VWM, LDWS, DMS, VCU, RCU, ACC, RWCD, PSU, BBM, AC_6000, TPMS, VMS, PEPS, IMMO, EMS, ESCL,MMI, BMS, FC, EC, ECM, CPD_3000, AFS, TCO, TCU, DCU,ECAS, ABS, EBS, EPB, AEBS, EVM, TCU_SH, ADAS, BS_LKA, CIM,RIM, FIM, MCU, CABS, DSW, VCU_x5_M3S, SWG, CCU, WP_ECU, CMS_ECU,EHBS, ACR, TBOX_5G, CSC, HCU, LKA, ADCU, CPD_6000, IC_3000, AC_3000,LE_IC, LE_AC, LE_BCM, LE_GW, LE_VCU, LE_TPMS, LE_DCM, VDCU, PDU, DCDC, DCAC,         DSSAD
}ECUs;typedef unsigned char	uint8; 
typedef unsigned short	uint16;       
// Function
//
KeyGenResult HD10GenerateKeyEx(uint8*       iSeedArray,	/* Array for the seed [in] */uint8			iSeedArraySize,	/* Length of the array for the seed [in] */const uint8	iSecurityLevel,	/* Security level [in] */uint8 *		iKeyArray,	/* Array for the key [in, out] */uint8 *		iKeySize,	/* Length of the key [out] */ECUs			e			/* enum ECUS elements */);#ifdef _cplusplus
}
#endif#endif // _HD10_safe_H_

        第三方动态库 libTXJsafe.so 如下:

C++调用

        写一个C++ demo 调用动态库 test.cpp 代码如下:

#include <stdio.h>
#include "HD10_safe.h"int main()
{uint8 arr[2] = {0x12, 0x34};uint8 seed[2] = {0x00, 0x00};uint8 seedLen = 0;int ret = HD10GenerateKeyEx(arr, 2, 7, seed, &seedLen, TCU);printf("ret : %d, seedLen:%d \n", ret, seedLen);for(int i = 0; i < seedLen; i++){printf("seed[%d] : 0x%02x ;", i, seed[i]);}printf("\n");return 0;
}

        运行结果如下:

jni二次封装动态库

        通过jni二次封装动态库 mysafelib.cpp 代码如下:

#include <iostream>
#include <stdio.h>
#include <jni.h>
#include <string.h>
#include "HD10_safe.h"// iString 输入参数格式:level(1byte) + ECUS(1byte) + SeedSize(1byte) + SeedValue(nbyte)
// rString 返回参数格式:keysize(1byte) + keyValue(nbyte)
extern "C" {JNIEXPORT jstring JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj, jstring iString);
}// 十六进制字符串转字十六进制 "12" --> 0x12
int Str2Hex(char *p_hexstr, int iHexLen, char *pdststr);// 十六进制数值转十六进制字符串 0x12 --> "12"
int Hex2Str(const char *p_strstr, int iStrLen, char *pdststr);JNIEXPORT jstring JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj, jstring iString)
{char myRString[66] = {0};char iHexStrOrg[64] = {0};char iHexStr[32] = {0};const char *iStrData = env->GetStringUTFChars(iString, 0);memcpy(iHexStrOrg, iStrData, strlen(iStrData) > 64 ? 64 : strlen(iStrData));env->ReleaseStringUTFChars(iString, iStrData);int iHexStrLen = Str2Hex(iHexStrOrg, strlen(iHexStrOrg), iHexStr);// std::cout << "strlen(iHexStrOrg) : " << strlen(iHexStrOrg) << std::endl;if(iHexStrLen < 4)	return env->NewStringUTF(myRString);// std::cout << "iHexStrLen : " << iHexStrLen << std::endl;uint8 seed[32] = {0};uint8 key[33] = {0};uint8 keyLen = 0;uint8 u8Level		= *(uint8 *)iHexStr;uint8 u8ECU	 		= *(uint8 *)(iHexStr + 1);uint8 u8SeedSize	= *(uint8 *)(iHexStr + 2);// printf("u8SeedSize : %d \n", u8SeedSize);if(u8SeedSize > 32)	return env->NewStringUTF(myRString);memcpy(seed, iHexStr + 3, u8SeedSize);KeyGenResult ret = (KeyGenResult)HD10GenerateKeyEx(seed, u8SeedSize, u8Level, key + 1, &keyLen, (ECUs)u8ECU);if(ret != KGRE_OK || keyLen > 32)	return env->NewStringUTF(myRString);// printf("ret : %d, keyLen:%d \n", (int)ret, keyLen);// for(int i = 1; i <= keyLen; i++)	printf("key[%d] : %02x; ", i, key[i]);key[0] = keyLen * 2;Hex2Str((const char*)key, keyLen + 1, myRString);jstring rString = env->NewStringUTF(myRString);printf("\n---------------successful-----------------\n");return rString;
}// 十六进制字符串转字十六进制 "12" --> 0x12
int Str2Hex(char *p_hexstr, int iHexLen, char *pdststr)
{int iret = 0;while(p_hexstr != NULL && pdststr != NULL && iHexLen > 1){char cTemp = '0';// printf("1:%c, 2:%c\n", p_hexstr[0], p_hexstr[1]);// 小写统一转大写if(p_hexstr[0] >= '0' && p_hexstr[0] <= '9'){cTemp = p_hexstr[0] - '0';}else if(p_hexstr[0] >= 'A' && p_hexstr[0] <= 'F'){cTemp = p_hexstr[0] - 'A' + 10;}else if(p_hexstr[0] >= 'a' && p_hexstr[0] <= 'f'){cTemp = p_hexstr[0] - 'a' + 10;}else{printf("the hex str is error!\n");break;}*pdststr = cTemp * 16;if(p_hexstr[1] >= '0' && p_hexstr[1] <= '9'){cTemp = p_hexstr[1] - '0';}else if(p_hexstr[1] >= 'A' && p_hexstr[1] <= 'F'){cTemp = p_hexstr[1] - 'A' + 10;}else if(p_hexstr[1] >= 'a' && p_hexstr[1] <= 'f'){cTemp = p_hexstr[1] - 'a' + 10;}else{printf("the hex str is error!\n");break;}*pdststr += cTemp;// printf("---iHexLen:%d, pdststr:%c\n", iHexLen, *pdststr);iHexLen -= 2;p_hexstr += 2;pdststr++;iret++;}// printf("iret : %d\n", iret);return iret;
}// 十六进制数值转十六进制字符串 0x12 --> "12"
int Hex2Str(const char *p_strstr, int iStrLen, char *pdststr)
{int index_str = 0, index_hex = 0;const char cHex[] = "0123456789ABCDEF";while(index_str < iStrLen && p_strstr != NULL && pdststr != NULL){pdststr[index_hex++] = cHex[((uint8)p_strstr[index_str])/16];pdststr[index_hex++] = cHex[((uint8)p_strstr[index_str++])%16];}return index_hex;
}

        编译生成对应二次封装的动态库如下:

java调用二次封装动态库

        java调用二次封装库的demo文件如下:

package com.example;public class MyClass {static {System.load("/home/lijd/testlib3/sodir/libmysafe.so"); // 加载C++动态库}private native String nativeMethod(String str); // 声明本地方法public static void main(String[] args) {byte[] seedValue = new byte[]{0x12, 0x34};int seedSize = 2;//字节长度int level = 7;int ECUS = 29;StringBuffer param = new StringBuffer();param.append(byteToString(intToByte1(level)));param.append(byteToString(intToByte1(ECUS)));param.append(byteToString(intToByte1(seedSize)));param.append(byteToString(seedValue));String result = new MyClass().nativeMethod(param.toString()); // 调用本地方法System.out.println("---MyClass---" + result.length() + " : " + result);}/*** @title byteToString* @description 将字节数组转为字符串* @param buff*            字节数据* @return String 装换后的字符串数据*/public static final String byteToString(byte[] buff) {StringBuilder sb = new StringBuilder();if (null != buff && buff.length > 0) {for (byte b : buff) {short t = b;if (t < 0)t += 256;short h = (short) (t / 16);short l = (short) (t % 16);switch (h) {case 10:sb.append("A");break;case 11:sb.append("B");break;case 12:sb.append("C");break;case 13:sb.append("D");break;case 14:sb.append("E");break;case 15:sb.append("F");break;default:sb.append(h);break;}switch (l) {case 10:sb.append("A");break;case 11:sb.append("B");break;case 12:sb.append("C");break;case 13:sb.append("D");break;case 14:sb.append("E");break;case 15:sb.append("F");break;default:sb.append(l);break;}}}return sb.toString();}public static byte[] intToByte1(int value) {byte[] b = new byte[1];for (int i = 0; i < 1; ++i) {int offset = (b.length - 1 - i) * 8;b[i] = (byte) (value >>> offset & 255);}return b;}
}

        执行javac 编译源文件生产class文件如下:

        运行java的class文件如下:

        至此,一切搞定!通过windows测试这样也完全可以。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用匿名labmda表达式对一个函数的参数是个函数类型的具体实现时的 双向回调数据 双向处理业务逻辑

双向回调数据 双向处理业务逻辑在android的应用场景就是:Activity界面的RecyclerView与Adapter双向的相互传递数据处理业务逻辑 class HigherOrderFunctionSuspendActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?){//简化前 num表示参…

卧槽!这项目开源了!【送源码 】

随着科技的飞速发展&#xff0c;个人财务管理变得越来越重要。一个名为‘Maybe’的创新型个人财务与财富管理应用程序随之诞生&#xff0c;它以其丰富的功能和用户友好的界面受到了广大用户的关注。 现在项目方将这个价值 100万美元的个人理财应用项目开源了 Maybe Maybe应用…

Attention as an RNN

摘要 https://arxiv.org/pdf/2405.13956 Transformer的出现标志着序列建模领域的一个重大突破&#xff0c;它提供了一种高性能架构&#xff0c;能够充分利用GPU并行性。然而&#xff0c;Transformer在推理时计算成本高昂&#xff0c;限制了其应用&#xff0c;特别是在资源受限的…

吴恩达2022机器学习专项课程C2W2:2.19 sigmoid函数的替代方案 2.20如何选择激活函数 2.21 激活函数的重要性

这里写目录标题 引言sigmoid激活函数的局限1.回顾需求案例2.ReLU激活函数 常用的激活函数1.线性激活函数的解释 如何选择激活函数&#xff1f;1.选择输出层的激活函数2.选择隐藏层的激活函数 选择激活函数的总结1.输出层总结2.隐藏层总结3.TensorFlow设置激活函数 激活函数多样…

AI生成视频解决方案,降低成本,提高效率

传统的视频制作方式往往受限于高昂的成本、复杂的拍摄流程以及硬件设备的限制&#xff0c;为了解决这些问题&#xff0c;美摄科技凭借领先的AI技术&#xff0c;推出了全新的AI生成视频解决方案&#xff0c;为企业带来前所未有的视觉创新体验。 一、超越想象的AI视频生成 美摄…

大模型时代的具身智能系列专题(四)

google deepmind团队 谷歌旗下最大的两个 AI 研究机构——地处伦敦 DeepMind 与位于硅谷的 Google Brain 合并成立新部门 Google DeepMind。其将机器学习和系统神经科学的最先进技术结合起来&#xff0c;建立强大的通用学习算法。代表作有AlphaGo&#xff0c;AlphaStar&#x…

SpringBoot集成mongodb

引入maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>添加yaml配置 spring:data:mongodb:uri: mongodb://localhost:27017/novel创建实体类…

鸿蒙ArkTS声明式开发:跨平台支持列表【组件快捷键事件】

组件快捷键事件 开发者可以设置组件的自定义组合键&#xff0c;组合键的行为与click行为一致&#xff0c;组件在未获得焦点状态下也可以响应自定义组合键&#xff0c;每个组件可以设置多个组合键。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-s…

Xshell远程连接服务器需要哪些依赖包、

在安装 Xshell 时&#xff0c;您需要确保系统中安装了必要的依赖库文件。这些依赖库文件对于 Xshell 的正常运行至关重要。虽然具体的依赖库文件可能会根据您的操作系统和安装环境有所不同&#xff0c;但通常包括以下几种&#xff1a; libXdmcp-devellibXinerama-devellibXft-…

香橙派 AiPro通过Micro USB接口进行串口调试

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、配置步骤1.安装CH343驱动2.配置串口参数 二、使用步骤总结 前言 最近在玩一个新玩具香橙派 AiPro&#xff0c;除了通过SSH方式连接开发板以外&#xff0c;…

Java优化代码攻略

一、背景 编码优化是Java开发中的关键步骤&#xff0c;它关注于提升代码可读性、性能和资源效率。常见技巧包括简化逻辑、减少冗余、利用缓存、优化数据结构等。例如&#xff0c;在电商系统中&#xff0c;通过缓存热门商品数据&#xff0c;可大幅提升页面加载速度&#xff1b;…

C++类与对象的特性

1.类的静态成员 静态成员包括静态成员变量和静态成员函数。使用静态成员变量可以实现类的数据成员的共享。 静态成员变量的值可以修改&#xff0c;并且对类的每个对象都相同,它是所有类对象共有的数据,对对象而言节约了空间。其存储空间的分配不在构造函数内完成&#…

华为机考入门python3--(32)牛客32-密码截取

分类&#xff1a;最长对称子串、动态规划 知识点&#xff1a; 生成二维数组 dp [[0] * n for _ in range(n)] 求最大值 max(value1, value2) 动态规划的步骤 a. 定义问题 长度为n下最长的对称子串的长度 b. 确定状态 dp[i][j]表示字符串从索引i到j的子串是否为对称…

关于Vue本地图片转file传到后端服务器(不通过组件上传)

一、代码 // 核心代码 const getMyFileFromLocalPath (localPath, filename) > {return fetch(localPath).then((response) > response.blob()).then((blob) > new File([blob], filename, { type: "image/png" })); // 假设是PNG格式// 获取真正的流文件…

Hibernate最新6万字面试题及参考答案

目录 什么是Hibernate? Hibernate的主要组件有哪些? 解释ORM(对象关系映射)的概念。

Vue3的setup系列篇之defineEmits和defineProps使用方式

父组件参数 <template><div><h2>子组件联动的与使用</h2><!-- reactive这样 --><!-- <childCom v-model:user"data.user" v-model"money" /> --><!-- ref这样 --><childCom v-model:user"user&q…

封装,static,代码块,对象的打印

封装&#xff0c;static&#xff0c;代码块&#xff0c;对象的打印 1. 封装1.1 封装的概念1.2 包的概念1.3 访问修饰限定符1.4 被封装的属性如何set和get&#xff1f; 2. static2.1 再谈学生类2.2 static修饰成员变量2.3 static修饰成员方法2.4 static成员变量初始化 3. 代码块…

IGMP——组播成员端网络协议

目录 一.IGMP基本概念 &#xff08;1&#xff09;组播转发困境 &#xff08;2&#xff09;感知组播成员方式 &#xff08;3&#xff09;IGMP版本 二.IGMP各版本的区别与联系 &#xff08;1&#xff09;IGMPV1 1.普遍组查询报文 2.成员关系报告报文 3.IGMPV1报文格式 4…

JavaScript日期与时间处理的艺术

JavaScript日期与时间处理的艺术 基础概念&#xff1a;JavaScript中的日期对象诞生时刻时间戳&#xff1a;纪元的秘密 案例一&#xff1a;格式化日期的艺术美化你的日期自定义格式化 案例二&#xff1a;跨时区的舞蹈时区转换 案例三&#xff1a;时间旅行的挑战闰年与月份天数避…

Go 项目如何打包在各个平台运行?

1 Windwos开发环境打包可执行文件 在Windows环境&#xff0c;我们可以将Golang的项目打包成不同平台的可执行文件。 1.1 打包Windows可执行文件 set GOOSwindows set GOARCHamd64 go build -o bin/app_win.exe1.2 打包Linux可执行文件 set GOOSlinux set GOARCHamd64 go …