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

news/2024/7/20 17:18:15/文章来源:https://blog.csdn.net/ddazz0621/article/details/139259459

        由于项目中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.luyixian.cn/news_show_1053250.aspx

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

相关文章

CSS文本粒子动画特效之爱心粒子文字特效-Canvas

1. 效果图 2.完整代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>body,html {margin: 0;paddin…

嵌入式学习——3——UDP TFTP简易文件传输

tftp协议概述 简单文件传输协议&#xff0c;适用于在网络上进行文件传输的一套标准协议&#xff0c;使用UDP传输 特点&#xff1a; 是应用层协议 基于UDP协议实现 数据传输模式 octet&#xff1a;二进制模式&#xff08;常用&#xff09; mail&#xff1a;已经不再支持 TFTP通信…

【Spring】深入学习AOP编程思想的实现原理和优势

【切面编程】深入学习AOP编程思想的实现原理和优势 前言AOP的由来及AOP与代理的关系AOP的实现方式详解静态代理动态代理 AOP的应用场景记录日志权限控制数据库事务控制缓存处理异常处理监控管理 AOP的底层实现全流程解析Spring AOP的简介动态代理的实现原理Spring AOP的实现原理…

易查分小程序 学生成绩管理小程序

亲爱的老师们&#xff0c;是不是每次成绩公布后&#xff0c;家长们的连环夺命call让你头大&#xff1f;担心孩子们的成绩信息安全&#xff0c;又想快速分享给家长&#xff0c;这可咋整&#xff1f;别急&#xff0c;易查分小程序来帮忙啦&#xff01; 安全有保障 智能验证码&a…

K8S集群监控方案之Prometheus+kube-state-metrics+Grafana

序言 | Prometheus 中文文档 方案简单架构图 一、部署kube-state-metrics 1、部署文件下载 地址 kube-state-metrics/examples/standard at main kubernetes/kube-state-metrics GitHub 2、修改下载的文件 2.1、修改镜像 原镜像可能下载不了&#xff0c;这里修改deploy…

43、Flink 的 Window Join 详解

1.Window Join a&#xff09;概述 Window join 作用在两个流中有相同 key 且处于相同窗口的元素上&#xff0c;窗口可以通过 window assigner 定义&#xff0c;并且两个流中的元素都会被用于计算窗口的结果。 两个流中的元素在组合之后&#xff0c;会被传递给用户定义的 Joi…

数据结构算法题day03

数据结构算法题day03 题目 题目 2.设计一个高效算法&#xff0c;将顺序表L的所有元素逆置&#xff0c;要求算法的空间复杂度为O(1)算法思想&#xff1a; 1、常规的解法&#xff1a; Void reverse (sqlist &L){Elemtype temp; //辅助变量for(i 0,i < L.length; i){temp…

Java RMI

RMI - 安全篇 RMI分为三个主体部分&#xff1a; *Client-客户端*&#xff1a;客户端调用服务端的方法 *Server-服务端*&#xff1a;远程调用方法对象的提供者&#xff0c;也是代码真正执行的地方&#xff0c;执行结束会返回给客户端一个方法执行的结果。 *Registry-注册中心…

【Python小案例】Python+mysql+PyQt5健康体检报告查询

下载安装Python3.7.8 python官网&#xff1a;https://www.python.org/ PyQt5配置 安装PyQt5 pip install PyQt5pip install qt5_toolspytcharm创建项目 配置外部工具 QTDesigner的Arguments语句不用填 QTDesigner的Working directory语句:$ProjectFileDir$ Pyuic的Argume…

OpenCV学习 基础图像操作(十四):直方图均衡化和直方图规定化

基础原理 直方图操作是基于像素统计的基础图像操作,被广泛运用于调整图像的对比度,并由此衍生出很多变种和该经的方式. 图像相直方图 直方图(Histogram)&#xff0c;又称质量分布图&#xff0c;是一种统计报告图&#xff0c;由一系列高度不等的纵向条纹或线段表示数据分布的…

GPT-4o和GPT-4有什么区别?我们还需要付费开通GPT-4?

GPT-4o 是 OpenAI 最新推出的大模型&#xff0c;有它的独特之处。那么GPT-4o 与 GPT-4 之间的主要区别具体有哪些呢&#xff1f;今天我们就来聊聊这个问题。 目前来看&#xff0c;主要是下面几个差异。 响应速度 GPT-4o 的一个显著优势是其处理速度。它能够更快地回应用户的查…

gin框架精通篇(二)

原生数据库使用 导入模块&#xff1a;go get -u github.com/go-sql-driver/mysql 安装 mysql 数据库 安装数据库可能遇到的问题&#xff1a;&#xff08;网上的方法基本可以解决&#xff09; ERROR 1045 (28000): Access denied for user ‘-root’‘localhost’ (using passwo…

模拟量4~20mA电流传感器接线方式

一、模拟量4~20mA电流传感器接线方式 无源双线制是常见的电流型传感器接线方式&#xff0c;它具有简单、经济的特点。其接线方式如下&#xff1a; 传感器的“”接到数据采集器的电源“”上&#xff0c; 传感器的“-”端子连接到数据采集器的“AI”端子上&#xff0c; 数据采集器…

深入分析C#中的“编写器”概念——代码修改、注解与重构

文章目录 1. 编写器&#xff08;Writer&#xff09;的概念2. 编写器的作用和工作原理3. 编写器的重要性4. 写入器常用方法5. 写入器示例6. 编写器示例——使用Fody进行代码注解和重构7. 总结 在软件开发过程中&#xff0c;代码的维护和更新是至关重要的。C#作为一种流行的编程语…

【RK3288 Android10 T8pro usb hid-multitouch idc配置】

【RK3288 Android10 T8pro usb hid-multitouch idc配置】 文章目录 【RK3288 Android10 T8pro usb hid-multitouch idc配置】背景代码分析1. 读取配置文件2. 标志内外置屏幕3. 设置输入设备4. findviewport()5. 根据对应的viewport来计算相应的mapping的参数 结论 背景 T8pro …

护网2024-攻防对抗解决方案思路

一、护网行动简介 近年来&#xff0c;网络安全已被国家上升为国家安全的战略层面&#xff0c;网络安全同样也被视为维护企业业务持续性的关键。国家在网络安全治理方面不断出台法规与制度&#xff0c;并实施了一些大型项目和计划&#xff0c;如网络安全法、等级保护、网络安全…

【NumPy】NumPy线性代数模块详解:掌握numpy.linalg的核心功能

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

HQChart使用教程99-K线窗口设置上下间距

HQChart使用教程99-K线窗口设置上下预留间距 指标窗口布局说明设置预留间距数据结构通过Setoption设置通过ChangeIndex设置 HQChart代码地址 指标窗口布局说明 顶部预留间距(3)和底部预留间距(5) 这个部分是算在Y轴坐标上的 设置预留间距 数据结构 HorizontalReserved&#…

【Qt QML】Dialog组件

带有标准按钮和标题的弹出对话框&#xff0c;用于与用户进行短期交互。 这个描述指的是一个常见的用户界面元素&#xff0c;即一个临时弹出的窗口&#xff08;或对话框&#xff09;&#xff0c;它包含一个标题&#xff0c;显示对话框的用途或内容描述&#xff0c;以及一系列标…

[最新]CentOS7设置开机自启动Hadoop集群

安装好Hadoop后我们可以使用开机自启动的方式&#xff0c;节约敲命令的时间。注意是centOS7版本!!!和centOS6版本区别非常大!!! 1、切换到系统目录 [rootmaster ~]# cd /etc/systemd [rootmaster systemd]# ll total 32 -rw-r--r-- 1 root root 720 Jun 30 23:11 bootcha…