参考资料:
https://blog.csdn.net/ctwy291314/article/details/82895604 Java JNA (三)—— 结构体使用及简单示例
https://www.jianshu.com/p/ead89497c403 JNA 教程
net.java.dev.jna
jna
5.5.0
2.1 项目中放在resource目录下
2.2 或者放在这目录下
2.3 打成jar包后,路径
linux: /usr/lib/
win:所有DLL放同级目录
2.4 自定义路径
public boolean addDllLocationToPath(String dllLocation)
{
try
{
System.setProperty("java.library.path", System.getProperty("java.library.path") + ";" + dllLocation);
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
}
catch (Exception e)
{
System.err.println("Could not modify path");
return false;
}
return true;
}
}
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {
// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
Java primitive types (and their object equivalents) map directly to the native C type of the same size.
Native Type | Size | Java Type | Common Windows Types |
char | 8-bit integer | byte | BYTE, TCHAR |
short | 16-bit integer | short | WORD |
wchar_t | 16/32-bit character | char | TCHAR |
int | 32-bit integer | int | DWORD |
int | boolean value | boolean | BOOL |
long | 32/64-bit integer | NativeLong | LONG |
long long | 64-bit integer | long | __int64 |
float | 32-bit FP | float | |
double | 64-bit FP | double | |
char* | C string | String | LPCSTR |
void* | pointer | Pointer | LPVOID, HANDLE, LPXXX |
Unsigned types use the same mappings as signed types. C enums are usually interchangeable with "int".
无符号类型的映射等同于有符号类型,如 unsigned short ->short ,枚举等同于int
struct CodeData
{
unsigned char code[4096];
unsigned short codeLen;
unsigned char orgId[8];
unsigned short orgIdLen;
};
@Structure.FieldOrder({"code", "codeLen", "orgId", "orgIdLen"})
public static class CodeData extends Structure {
//二维码数据 4096,要和dll的大小一致
public byte[] code = new byte[4096];
// 二维码数据长度 4096
public short codeLen;
//机构id
public byte[] orgId;
//机构id长度8
public short orgIdLen;
//这个类代表结构体指针
public static class ByReference extends CodeData implements Structure.ByReference {
}
//这个类代表结构体本身
public static class ByValue extends CodeData implements Structure.ByValue {
}
}
注意事项:
1.Structure 子类中的公共字段的顺序,必须与C 语言中的结构的顺序一致。否则会报错!
2.C语言结构中的char数组指定了大小,则使用byte需要指定大小,不能使用String,原因我猜是因为内存块?
3.或者使用指针,初始化时指定大小
unsigned char getData (struct CodeData *code,unsigned char *str,unsigned short len, unsigned char *data,unsigned short *dataLen);
/**
* 获取数据
*
* @param codeData 结构体指针入参
* @param str 字符串入参
* @param len 基础类型入参
* @param data 字符串出参
* @param dataLen 基础类型出参
* @return
*/
byte getData(CodeData.ByReference codeData,String str, short len, byte[] data, ShortByReference dataLen);
public static String getData() {
String orgId = "12345678";
String code = "123456789";
String str = "test";
String len = 4;
CtidLibrary.CodeData.ByReference codeData = new CtidLibrary.CodeData.ByReference();
codeData.orgId = orgId.getBytes();
codeData.orgIdLen = 8;
byte[] codeTmp = code.getBytes();
for (int i = 0; i < codeTmp.length; i++) {
codeData.code[i] = codeTmp[i];
}
codeData.codeLen = (short) code.length();
byte[] data = new byte[1024];
ShortByReference dataLen = new ShortByReference();
byte resp = CtidLibrary.INSTANCE.getData(codeData, str, len, data, dataLen);
System.out.println(resp);
String result = new String(data);
System.out.println(result);
return result;
}
注:出参和入参格式可能不一样
1.dll库如果是32位的,JDK也要改成32位的。
2.dll存在依赖关系,先引入父级的依赖,具体如下:
2.1 依赖项
public interface MklIntelThreadLibrary extends Library {
MklIntelThreadLibrary INSTANCE = Native.load("mkl_intel_thread", MklIntelThreadLibrary.class);
}
2.2 需要调用的dll
public interface AntiSpoofLibrary extends Library {
MklIntelThreadLibrary mkl = MklIntelThreadLibrary.INSTANCE;
AntiSpoofLibrary INSTANCE = Native.load("AntiSpoof", AntiSpoofLibrary.class);
/**
* 初始化接口,返回:true正确,false错误
*
* @return
*/
boolean InitSpoof(String modelPath);
/**
* 活体检测接口 ,返回:true 活体,false:假体
*
* @return
*/
boolean AntiSpoofBase64(String rgbBase, String irBase, boolean print);
}
3.Invalid memory access
可能原因:1.数据类型映射不对
2.不支持多线程,调用时需要使用同步代码块