我是靠谱客的博主 满意航空,这篇文章主要介绍SpringBoot 使用JNA 调用DLL过程以及遇到的问题总结,现在分享给大家,希望可以做个参考。

参考资料:

https://blog.csdn.net/ctwy291314/article/details/82895604 Java JNA (三)—— 结构体使用及简单示例

https://www.jianshu.com/p/ead89497c403   JNA 教程

1.引入依赖

复制代码
1
2
3
4
5
6
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.5.0</version> </dependency>

2.存放DLL路径

2.1 项目中放在resource目录下

2.2 或者放在这目录下 

 

2.3 打成jar包后,路径

复制代码
1
2
linux: /usr/lib/ win:所有DLL放同级目录

2.4 自定义路径

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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; } }

 

3.继承library

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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, Worldn"); for (int i=0;i < args.length;i++) { CLibrary.INSTANCE.printf("Argument %d: %sn", i, args[i]); } } }

 

4.数据类型映射

Java primitive types (and their object equivalents) map directly to the native C type of the same size.

Native TypeSizeJava TypeCommon Windows Types
char8-bit integerbyteBYTE, TCHAR
short16-bit integershortWORD
wchar_t16/32-bit charactercharTCHAR
int32-bit integerintDWORD
intboolean valuebooleanBOOL
long32/64-bit integerNativeLongLONG
long long64-bit integerlong__int64
float32-bit FPfloat 
double64-bit FPdouble 
char*C stringStringLPCSTR
void*pointerPointerLPVOID, HANDLE, LPXXX

Unsigned types use the same mappings as signed types. C enums are usually interchangeable with "int".

无符号类型的映射等同于有符号类型,如 unsigned short ->short ,枚举等同于int

5.结构体映射

复制代码
1
2
3
4
5
6
7
struct CodeData { unsigned char code[4096]; unsigned short codeLen; unsigned char orgId[8]; unsigned short orgIdLen; };
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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.或者使用指针,初始化时指定大小

6.函数映射

复制代码
1
2
unsigned char getData (struct CodeData *code,unsigned char *str,unsigned short len, unsigned char *data,unsigned short *dataLen);
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
/** * 获取数据 * * @param codeData 结构体指针入参 * @param str 字符串入参 * @param len 基础类型入参 * @param data 字符串出参 * @param dataLen 基础类型出参 * @return */ byte getData(CodeData.ByReference codeData,String str, short len, byte[] data, ShortByReference dataLen);

7.调用函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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; }

注:出参和入参格式可能不一样

8.注意事项

1.dll库如果是32位的,JDK也要改成32位的。

2.dll存在依赖关系,先引入父级的依赖,具体如下:

 2.1  依赖项

复制代码
1
2
3
public interface MklIntelThreadLibrary extends Library { MklIntelThreadLibrary INSTANCE = Native.load("mkl_intel_thread", MklIntelThreadLibrary.class); }

2.2 需要调用的dll

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.不支持多线程,调用时需要使用同步代码块

 

最后

以上就是满意航空最近收集整理的关于SpringBoot 使用JNA 调用DLL过程以及遇到的问题总结的全部内容,更多相关SpringBoot内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部