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" {
#endif

typedef	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测试这样也完全可以。

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

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

相关文章

河南道路与桥梁乙级资质升级门槛条件解读

河南道路与桥梁乙级资质升级门槛条件解读如下&#xff1a; 一、企业基本条件 法人资格&#xff1a; 企业需具备独立企业法人资格&#xff0c;能够独立承担民事责任。注册资金&#xff1a; 企业的注册资金应不少于100万元人民币&#xff0c;这一数字直接体现了企业的经济实力和…

Python自然语言处理(NLP)库之NLTK使用详解

概要 自然语言处理(NLP)是人工智能和计算机科学中的一个重要领域,涉及对人类语言的计算机理解和处理。Python的自然语言工具包(NLTK,Natural Language Toolkit)是一个功能强大的NLP库,提供了丰富的工具和数据集,帮助开发者进行各种NLP任务,如分词、词性标注、命名实体…

基于springboot实现医疗挂号管理系统项目【项目源码+论文说明】

基于springboot实现医疗挂号管理系统演示 摘要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&…

计算机tcp/ip网络通信过程

目录 &#xff08;1&#xff09;同一网段两台计算机通信过程 &#xff08;2&#xff09;不同网段的两台计算机通信过程 &#xff08;3&#xff09;目的主机收到数据包后的解包过程 &#xff08;1&#xff09;同一网段两台计算机通信过程 如果两台计算机在同一个局域网中的同…

C语言-02_变量与进制

文章目录 1.关键字2.标识符3.变量3.1 变量的声明与赋值3.2 变量的作用域3.3 变量按类型的分类 4.基本数据类型4.1 整数类型4.1.1 类型说明4.1.2 举例4.1.3 后缀4.1.4 整型的极限值 4.2 浮点类型4.2.1 类型说明4.2.2 举例 4.3 字符类型4.4 布尔类型 5.变量间的运算规则5.1 隐式类…

深入解析绘图范式:面向对象与直接操作的较量

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 第一节&#xff1a;面向对象绘图的魅力 第二节&#xff1a;直接操作绘图模块的便捷性 第三…

浙江大学数据结构MOOC-课后习题-第十讲-排序4 统计工龄

题目汇总 浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024 题目描述 测试点 思路分析 这道题很明显就是利用桶排序的思路 受到课程内容的影响&#xff0c;我一开始是想着建立一个链表数组&#xff0c;数组内每个元素下方都存放链表&#xff0c;最后再遍历统计输出。 但是&…

绝招曝光!3小时高效利用ChatGPT写出精彩论文

在这份指南中&#xff0c;我将深入解析如何利用ChatGPT 4.0的高级功能&#xff0c;指导整个学术研究和写作过程。从初步探索研究主题&#xff0c;到撰写结构严谨的学术论文&#xff0c;我将一步步展示如何在每个环节中有效运用ChatGPT。如果您还未使用PLUS版本&#xff0c;可以…

探索python数据可视化的奥秘:打造专业绘图环境

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、搭建专业绘图环境 二、掌握绘图基本原理 三、解锁绘图高级技巧 四、总结与展望 在数据…

操作系统—简要分析FAT文件系统

文章目录 简要分析FAT文件系统1.FAT的起源与发展历史2.FAT的基本结构与目录管理机制(1).基本结构(2).文件分配表(3).根目录区(4).数据区 3.优点与缺点4.改进与替代方案(1).exFAT(2).ext2/3/4(3).NTFS 小结参考文献 简要分析FAT文件系统 1.FAT的起源与发展历史 为了更好地管理磁…

买了份KFC,意外理解了5种 IO 模型

买了份KFC&#xff0c;意外理解了5种 IO 模型 前言一、基本概念1.1 简单介绍几个系统调用函数1.2 同步&异步1.3 阻塞&非阻塞 二、阻塞IO模型三、非阻塞IO模型四、IO多路复用模型五、信号驱动IO模型六、异步IO模型七、Java中的BIO&#xff0c;NIO&#xff0c;AIO7.1 BIO…

​LabVIEW超声波检测

LabVIEW超声波检测 在现代工业生产和科学研究中&#xff0c;超声检测技术因其无损性、高效率和可靠性而被广泛应用于材料和结构的缺陷检测。然而&#xff0c;传统的超声检测仪器往往依赖于操作者的经验和技能&#xff0c;其检测过程不够智能化&#xff0c;且检测结果的解读具有…

考研经验总结——复试上岸(附通信原理)

上岸啦&#xff0c;一志愿拟录取&#xff0c;初试第5、复试4&#xff0c;总成绩第4 文章目录 一、复试流程二、注意事项三、简历模板3.1 基本信息3.2 报考情况3.3 校内实践3.4 荣誉奖励3.5 项目经验3.6 自我介绍 四、通信原理五、最后的总结 一、复试流程 1、 复试流程 准备复…

【机器学习聚类算法实战-5】机器学习聚类算法之DBSCAN聚类、K均值聚类算法、分层聚类和不同度量的聚集聚类实例分析

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

STM32建立工程问题汇总

老版本MDK&#xff0c;例如MDK4 工程内容如下&#xff1a; User文件夹中存放main.c文件&#xff0c;用户中断服务函数&#xff08;stm32f1xx.it.c&#xff09;&#xff0c;用户配置文件&#xff08;stm32f1xx_hal_conf.h&#xff09;等用户程序文件&#xff0c;或者mdk启动程序…

彩光赋能中国智造 极简光3.X助力“数智”转型

蒸汽时代、电气时代、信息时代三大工业革命后 互联网和智能制造主导的工业4.0时代来临 大数据、云计算、人工智能等新兴技术 对企业园区的网络架构、负载能力等 提出了新要求,也使得光纤较于传统铜缆 在距离、性能、延时上的优势日益凸显 基于此 围绕未来园区网建设的企…

VB.net 进行CAD二次开发(二)

利用参考文献2&#xff0c;添加面板 执行treeControl New UCTreeView()时报一个错误&#xff1a; 用户代码未处理 System.ArgumentException HResult-2147024809 Message控件不支持透明的背景色。 SourceSystem.Windows.Forms StackTrace: 在 System.Windows…

界面组件Kendo UI for Angular教程 - 构建强大的PDF阅读器(二)

如今当用户需要处理PDF文件时&#xff0c;通常不得不下载应用程序或者浏览器插件&#xff0c;控制用户如何与PDF交互并不是一件容易的事。如果我们提供PDF作为内容&#xff0c;用户可以下载它并使用浏览器或PDF本身提供的控件进行交互。然而&#xff0c;一些企业可能希望控制用…

mysql去除重复数据

需求描述 doc表有很多重复的title,想去除掉重复的记录 表结构 CREATE TABLE doc (id INT PRIMARY KEY,title VARCHAR(255),content TEXT );去重SQL -- 创建临时表 CREATE TEMPORARY TABLE temp_doc AS SELECT * FROM doc WHERE 10;-- 插入唯一的记录&#xff08;每个title最…

idea中快速找到当前git地址

idea中快速找到当前git地址 然后双击就可以看到地址了