Java调用C++含char *类型参数的DLL文件

最近课程作业完成MD5加密的DLL编写,并使用Java调用DLL,中间遇到几个坑与君共勉。

一、C++编写MD5加密DLL

//定义外部调用宏
#ifdef MD5_DLL
#else
#define MD5_DLL extern "C" _declspec(dllexport) //指的是允许将其给外部调用
#endif
//声明接口,内容暂不展示
MD5_DLL void MD5(unsigned char* input, unsigned char* output);

二、JNA包下载

java native interface JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架,比JNI更好用,JNI偏底层,JNA更友好。
JNA下载地址:https://github.com/java-native-access/jna
找到Download下载第一个就OK
在这里插入图片描述

三、DLL转换

eclipse为例,右键项目->Properties->Java Build Path->Libraries->Add External JARs 选择JNA

1、编写charReference类,该类继承com.sun.jna.ptr.ByReference类,该类主要负责Java数据类型到C++中char *类型对应

import com.sun.jna.ptr.ByReference;

public class charReference extends ByReference{
	
	public charReference() {
		this((byte)0);//无
	}
	
	public charReference(byte value) {
		super(1000);
		this.setValue(value);
	}
	
	public void setValue(byte value) {
        this.getPointer().setByte(0L, value);
    }
	
	public byte getValue() {
        return this.getPointer().getByte(0L);
    }
	
	public void Init(String input) {
		for(int i=0;i<input.length();i++) {
			this.getPointer().setChar((long)i, input.charAt(i));//字符串初始化
		}
	}
	
	public void Init(byte[] bytes) {
		for(int i=0;i<bytes.length;i++) {
			this.getPointer().setByte((long)i, bytes[i]);//字节数组初始化
		}
	}

}

因为char可能是中文汉字,中文汉字占两个字节,在setChar时并不会将两个字节都传到对象中,所以有中文时需要先将字符串转化成字节数组再传。

2、声明接口

import com.sun.jna.*;
import com.sun.jna.ptr.PointerByReference;

import tools.charReference;
public interface PORT extends Library{
	PORT INSTANTCE=(PORT)Native.loadLibrary("MD5",PORT.class);//MD5为DLL文件名
	public void MD5(charReference input,charReference output);
}

将DLL文件放在项目bin文件夹下

3、MD5的JAVA实现

import java.io.UnsupportedEncodingException;
import com.sun.jna.*;
import com.sun.jna.ptr.PointerByReference;
import tools.byteToString;
import tools.PORT;
import tools.charReference;

public class MD5Encoder {
	//获得byte数组
	private static byte[] getBytes(String input) throws UnsupportedEncodingException {
		int byteLen=0;
		byte[] bytes=new byte[3*input.length()];
		for(int i=0;i<input.length();i++) {
			char now=input.charAt(i);
			byte[] nowCharBytes=null;
			if(isChinese(now)) {
				nowCharBytes=(""+now).getBytes("utf-8");
			}else {
				nowCharBytes=(""+now).getBytes();
			}
			for(int j=0;j<nowCharBytes.length;j++) {
				bytes[byteLen++]=nowCharBytes[j];
			}
		}
		return bytes;
	}
	//判断是否为中文
	private static final boolean isChinese(char c) {   
	    Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);  
	    if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS  
	            || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS  
	            || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A  
	            || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION  
	            || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION  
	            || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {  
	        return true;  
	    }  
	    return false;  
	}
    //加密
	public static String encoder(String inputString) throws UnsupportedEncodingException {
		charReference output=new charReference();
		charReference input=new charReference();
		input.Init(getBytes(inputString));
		PORT.INSTANTCE.MD5(input, output);
		String outputString="";
		for(int i =0;i<16;i++) {
			outputString=outputString+byteToString.bytesToHexString(output.getPointer().getByte(i));
		}
		return outputString;
	}
	//测试
	public static void main(String[] args) throws UnsupportedEncodingException {
		charReference output=new charReference();
		charReference input=new charReference();
		String x="zx哈哈";
		input.Init(getBytes(x));
		PORT.INSTANTCE.MD5(input, output);
		String outputString="";
		for(int i =0;i<16;i++) {
			outputString=outputString+byteToString.bytesToHexString(output.getPointer().getByte(i));
		}
		System.out.println(outputString);
	}
}

byteToString.byteToHexString为另一个类中的字节数组转化成字符串的函数

public static String bytesToHexString(byte src) {
        int v = src & 0xFF;
        String hv = Integer.toHexString(v);
        if(hv.length()==1) {
        	return "0"+hv;
        }
        return hv;
    }

运行结果:
在这里插入图片描述
与某网站(https://md5jiami.51240.com/)加密结果相同
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eShows

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值