大家都知道用C++编写的程序如果用于windows使用则编译为xxx.dll文件,如果是Linux使用则编译为libxxx.so文件。下面将java调用dll/so文件的方法粘出来方便下次使用。此处使用的jna的方式

jna可以从官方下载,也可以从maven里面去引用,下面是引用代码:

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.2.2</version>
</dependency>

先把C++的一段代码粘出来参考。

#pragma once
#include <stdint.h>
#ifdef __linux
#define _APICALL
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#else
#define DLL_PUBLIC
#define _APICALL __stdcall
#endif // __linux static const int8_t CRYPTTYPE_SM2 = ; // 非对称加密,SM2官方推荐模式(256bit加密强度)
static const int8_t CRYPTTYPE_SM4CBC = ; // 对称分组加密,SM4 CBC模式(128bit加密强度)
enum //错误码
{
GMC_ERR_OK = , //成功
GMC_ERR_CryptoTypeNotSupport = , //不支持该密码系统
GMC_ERR_PubKeyLost = , //公钥未设置
GMC_ERR_PriKeyLost = , //私钥未设置
GMC_ERR_OperationNotSupportThisCryptoType = , //操作不支持目前的密码系统类型。
GMC_ERR_SMALLMEMSIZE = , //相关内存长度过小
GMC_ERR_BADALLOCATE = , //内存分配失败
GMC_ERR_KEY_LENGTH = , //KEY长度不符合
GMC_ERR_KEY_FORMAT = , //KEY格式不符合
GMC_ERR_PARAM = , //参数错误
GMC_ERR_OPENSSL_INTERERR = , //openssl 内部错误
GMC_ERR_CIPHER = , //CIPHER相关错误
GMC_ERR_CIPHERTYPE_NOTSUPPORT = , //不支持的cipher类型
GMC_ERR_CIPHER_NOTINIT = , //未初始化
GMC_ERR_CIPHER_NOTSETKEY = , //没有设置KEY
GMC_ERR_SM2 = , //sm2相关错误码
GMC_ERR_SM2_NOTINIT =, //未初始化
GMC_ERR_SM2_NOTSETKEY = , //未设置 公钥或者私钥
};
extern "C"
{
/*
函数:GMC_New_CTX
功能:初始化获取一个指定类型的密码体系。
参数:
type:密码系统类型
返回:成功返回上下文指针,失败返回NULL。如果返回失败这表明不支持type指定的类型。
Note:在相关使用完成后需要调用GMC_Delete_CTX函数进行释放资源。
*/
DLL_PUBLIC void* _APICALL GMC_New_CTX(int8_t type);
/*
函数:GMC_Delete_CTX
功能:释放指定的密码体系上下文
参数:
pCtx:指定密码体系上下文
返回:无
*/
DLL_PUBLIC void _APICALL GMC_Delete_CTX(void *pCtx);
/*
函数:GMC_set_Key
功能:用于对称加密设置密钥
参数:
pKey:密钥(16进制数据的字符串化形式)
返回指:成功返回0,失败见错误码
*/
DLL_PUBLIC long _APICALL GMC_set_Key(void *pCtx,const char *pszKey);
/*
函数:GMC_ECKEY_set_PublicKey
功能:椭圆曲线加密系统公钥设置
参数:
pszXKey:X坐标(16进制数据的字符串化形式)
pszYKey:Y坐标(16进制数据的字符串化形式)
返回:成功返回0,失败见错误码
*/
DLL_PUBLIC long _APICALL GMC_ECKEY_set_PublicKey(void *pCtx,const char *pszXKey, const char *pszYKey);
/*
函数:GMC_ECKEY_set_PrivateKey
功能:椭圆曲线加解密系统私钥设置
参数:
pszXKey:私钥(16进制数据的字符串化形式)
返回:成功返回0,失败见错误码
*/
DLL_PUBLIC long _APICALL GMC_ECKEY_set_PrivateKey(void *pCtx,const char *pszKey);
/*
函数:GMC_Encrypt
功能:加密指定数据
参数:
pData:被加密数据地址
cbData:被加密数据长度
pEncrypttedData[out]:用于保存加密数据的地址(可以与pData内存重叠)
pcbEncryptted[int][out]:in:pEncrypttedData内存的大小,out:加密后数据的长度
返回:见错误码
note:参数pEncrypttedData可以为NULL,如果为NULl则pcbEncryptted参数返回需要长度。
*/
DLL_PUBLIC long _APICALL GMC_Encrypt(void *pCtx,const unsigned char *pData, uint32_t cbData, unsigned char *pEncrypttedData, uint32_t *pcbEncryptted);
/*
函数:GMC_Decrypt
功能:解密指定数据
参数:
pData:被解密数据地址
cbData:被解密数据长度
pDecrypttedData[out]:用于保存解密数据的地址(可以与pData内存重叠)
pcbDecryptted[int][out]:in:pDecrypttedData内存的大小,out:解密后数据的长度
返回:见错误码
note:参数pDecrypttedData可以为NULL,如果为NULl则pcbDecryptted参数返回需要长度。
*/
DLL_PUBLIC long _APICALL GMC_Decrypt(void *pCtx,const unsigned char *pData, uint32_t cbData, unsigned char *pDecrypttedData, uint32_t *pcbDecryptted);
/*
函数:GMC_GetLastErrMsg
功能:获取最后一次错误消息
参数:无
返回值:错误消息字串,返回值指针值必定不为NULL
*/
DLL_PUBLIC const char * _APICALL GMC_GetLastErrMsg();
}

然后就就介绍java的调用方法。什么引用jna就不说了。

一、创建一个接口并继承于com.sun.jna.Library(这里只实现了C++的部分方法)

public interface gmcrypto extends Library {
gmcrypto INSTANCE = (gmcrypto) Native.loadLibrary("gmcrypto", gmcrypto.class); /**
* 初始化获取一个指定类型的密码体系。
* @param type
*/
IntByReference GMC_New_CTX(long type); /**
* 获取上次的错误信息
* @return
*/
String GMC_GetLastErrMsg(); /**
* 加密,注意加密前先获取长度
* @param intByReference
* @param pData
* @param cbData
* @param pEncrypttedData
* @param pcbEncryptted
* @return
*/
long GMC_Encrypt(IntByReference intByReference, byte[] pData, int cbData, byte[] pEncrypttedData, IntByReference pcbEncryptted); /**
* 释放资源上下文
* @param intByReference
*/
void GMC_Delete_CTX(IntByReference intByReference);
}

二、在普通主方法中就可以调用了

public static void main2(String[] args) {
IntByReference gm = gmcrypto.INSTANCE.GMC_New_CTX(1);
if (gm == null) {
System.err.println("指定密码体系:失败");
} else {
/****************解密******************/
byte[] inByte = Base64.getDecoder().decode("MHYCIFnXBM5gF7OF4VYVmPh+exzQi9ik8dZBAFYs0hKrr8WRAiEArIjXQyOR1vdraQcdv9kG9/NGwVCEJ/UKIGw6gKcrTc0EIABJ7041HF7OLvzcSLvPVWDz3zjKWxOBu91someJ7D1+BA2tOEJsGFtH5rYu2Sxn");
long res = gmcrypto.INSTANCE.GMC_ECKEY_set_PrivateKey(gm, "C51F66571D5C472E383939D3C8944599D50452F4D8909B0C989C68888C0A1509");
System.out.println("设置私钥结果:" + res); IntByReference total = new IntByReference(1);
res = gmcrypto.INSTANCE.GMC_Decrypt(gm, inByte, inByte.length, null, total);
System.out.println(res + "\t" + total.getValue()); byte[] outByte = new byte[total.getValue()];
res = gmcrypto.INSTANCE.GMC_Decrypt(gm, inByte, inByte.length, outByte, total);
byte[] temp=new byte[total.getValue()];
System.arraycopy(outByte, 0, temp, 0, temp.length);
outByte=temp; System.out.println("解密结果:" + res + " 长度:" + outByte.length);
System.out.println(new String(outByte)); System.out.println("最近错误:" + gmcrypto.INSTANCE.GMC_GetLastErrMsg());
gmcrypto.INSTANCE.GMC_Delete_CTX(gm);
} }

重要说明:

1、gmcrypto就代表需要引用的dll/so文件的名称,由于java是跨平台,所以不加后缀,文件名为gmcrypto.dll/libgmcrypto.so

2、java中可以用IntByReference对象代表指针

3、windows需要把dll文件放到C:\Windows\System32路径。Linux需要把so文件放到/lib64。当然要根据情况区分32位和64位的情况

java调用dll/so文件的更多相关文章

  1. java调用dll或so动态库文件(c++/c)

    java调用dll或so动态库文件(c++/c) 博客分类:  工作 CC#C++JavaEclipse  java调用dll或so动态库文件(c++/c)开发平台:Eclipse3.3.1.1+CD ...

  2. Java 调用Dll

    Java 中怎么能调用到dll中的函数呢? 关键是java中生的本地函数名參数和dll中的本地函数名參数一模一样. 这个程序是java中调用dll中的求和函数. 一,java代码部分操作 1.新建pr ...

  3. 获取DLL的文件路径以及调用DLL的文件路径

    如何在DLL中,获取DLL本身的路径以及调用DLL的文件的路径呢?主要通过GetModuleFileName(HMODULEhModule,LPTSTR lpFilename,DWORD nSize) ...

  4. Java调用dll动态库

    最近项目里使用java调用dll动态库,因此研究了一下这方面的东西. 使用的工具包如下 <dependency> <groupId>net.java.dev.jna</g ...

  5. Java 调用 groovy 脚本文件,groovy 访问 MongoDB

    groovy 访问 MongoDB 示例: shell.groovy package db import com.gmongo.GMongoClient import com.mongodb.Basi ...

  6. Java调用.dll文件

    因为项目的需求,要在JAVA项目中调用Windows的Dll(动态链接库)文件,之前用Jni调用过C写的Dll文件,比较麻烦,这里不多说,网上也有很多这方面的文档.在网上找到一个开源的组件JNativ ...

  7. Java 调用 C++ (Java 调用 dll)康哥手把手教你

    摘要: 本文原创,转载请注明地址 http://www.cnblogs.com/baokang/p/4979243.html 因为要做点图形处理的项目,需要在Java中调用dll库,所以开发的第一步是 ...

  8. Java调用DLL有多种方式,常用的方式有JNative、JNA、JNI等。

    JNative方式调用dll JNative是一种能够使Java语言使调用DLL的一种技术,对JNI进行了封装,可能有些读者会有这样一个问题,JNative对JNI进行了封装,并且是一种跨语言的使用D ...

  9. (转)Java 调用 C++ (Java 调用 dll)

    转自: http://www.cnblogs.com/baokang/p/4979243.html 因为要做点图形处理的项目,需要在Java中调用dll库,所以开发的第一步是研究了一下Java Jni ...

随机推荐

  1. linux homebrew skill 技巧

    $ cat /usr/bin/gitdiffH0#!/bin/bashgit diff HEAD $(git ls-files| grep '\.py$\|\.py\.in$') | osflake8 ...

  2. 如何用Tensorflow训练模型成pb文件和和如何加载已经训练好的模型文件

    这篇薄荷主要是讲了如何用tensorflow去训练好一个模型,然后生成相应的pb文件.最后会将如何重新加载这个pb文件. 首先先放出PO主的github: https://github.com/ppp ...

  3. OpenCV常用库函数[典]

    一.core 模块 1.Mat - 基本图像容器 Mat 是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是 ...

  4. Navicat Premium 12.0.18安装与激活(转)

    转载:https://www.jianshu.com/p/42a33b0dda9c 一.Navicat Premium 12下载 Navicat Premium 12是一套数据库开发管理工具,支持连接 ...

  5. 2018年11月20日 远交近攻 list1

    list 列表用法 li=[1,2,3,"abc"] #列表中的元素,可以为数字或者字符串或者布尔值或者就是列表等,所有都能放进去 #列表中也能嵌套列表 pi=[1,2,3,[2, ...

  6. topcoder srm 500 div1

    problem1 link 如果decisions的大小为0,那么每一轮都是$N$个人.答案为0. 否则,如果答案不为0,那么概率最大的一定是一开始票数最多的人.因为这个人每一轮都在可以留下来的人群中 ...

  7. Python3基础 list enumerate 将列表的每个元素转换成 带索引值的元组

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  8. tp框架中的一些疑点知识--cookie和session的配置

    不同的浏览器采用不同的方式保存Cookie. IE浏览器会在"C:\Documents and Settings\你的用户名\Cookies"文件夹下以文本文件形式保存,一个文本文 ...

  9. 买不到的数目|2018年蓝桥杯A组题解析第八题-fishers

    买不到的数目 小明开了一家糖果店.他别出心裁:把水果糖包成4颗一包和7颗一包的两种.糖果不能拆包卖. 小朋友来买糖的时候,他就用这两种包装来组合.当然有些糖果数目是无法组合出来的,比如要买 10 颗糖 ...

  10. FJNU2018低程F jq解救fuls (贪心乱搞)题解

    题目描述 一天fuls被邪恶的"咕咕咕"抓走了,jq为了救fuls可谓是赴汤蹈火,费了九牛二虎之力才找到了"咕咕咕"关押fuls的地方. fuls被关在一个机关 ...