目录
3.Java使用JNA调用dll出现 Invalid memory access错误
9.java.lang.IllegalArgumentException: Unsupported array argument type: class [F
前言
java 调用so,dll相关问题整理
jdk 1.8
jna 4.1.0
一、Jna是什么?
提到JNA 就不得不提一下JNI(Java Native Interface),有过不同语言间通信开发经历的一般都知道,它允许java和其他语言代码(尤其是C/C++)进行交互,只要遵守约定即可
二、问题整理
1.linux 读取不到so动态库
解决如下:
linux环境下 读取so动态库方式两种方式
1.将so动态库放在 /usr/lib 中
2.将so名称加入前缀 libxxx.so,放在 linux-x86-64
2.函数名不对出现的异常
java.lang.UnsatisfiedLinkError: Error looking up function 'Recognition': /tmp/jna-3506402/jna595594145827778689.tmp: undefined symbol: Recognition
核对函数名,参数等
3.Java使用JNA调用dll出现 Invalid memory access错误
想着应该是数据类型转换出现了错误。例如dll方法中出现了int*,我仿着delphi用int去映射。问题就在这里,JNA关于指针映射这块有自己的类型。int*对应的是IntByReference这个类型(其他指针类型转换参照JNA指针映射 )。改正类型后,程序成功运行。
4.64位调用32位dll找不到问题
java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序。
安装32位jdk ,jdk-8u301-windows-i586.exe
固定目录存放在resource下
linux-64 | linux-x86-64 |
win32 | win32-x86 |
win64 | win32-x86-64 |
创建win32-x86目录,dll放在其下
5.动态库关联路径不对,导致不执行
放到 C:\Program Files (x86)\Java\jdk1.8.0_301\bin 下正常
6.类型对应不正确也会出现输出值不对
uint8_t | byte |
uint16_t | short |
uint32_t | long/ int |
7.文件位置,系统位数都正确,执行报模块找不到
解决方式:看动态库的原语言运行环境是否正确。
8.结构体类型返回值
- 构造结构体
public interface Test1Library extends Library {
Test1Library DIAGNOSIS = (Test1Library) Native.loadLibrary("diagnosis_dll", Test1Library.class);
DiagnosisResponse.ByValue func_realization(float i1[], int size1);
class DiagnosisResponse extends Structure{
public float D_I1n;
public float D_I2n;
public static class ByValue extends DiagnosisResponse implements Structure.ByValue
{
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[]{"D_I1n", "D_I2n"});
}
}
}
- 调用 Test1Library.DiagnosisResponse diagnosisResponse = INSTANCE.func_realization(diagnosisRequest.getI1(), diagnosisRequest.getI1Size());
9.java.lang.IllegalArgumentException: Unsupported array argument type: class [F
问题原因是 java 调用动态库传递二维数组
public class ForecasRequest extends Structure {
public float[] forecast = new float[2];
public static class ByReference extends ForecasRequest implements Structure.ByReference {}
public static class ByValue extends ForecasRequest implements Structure.ByValue {}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[]{"forecast"});
}
}
通过结构体来传递二维数组
ForecasRequest[] forecas = (ForecasRequest[]) new ForecasRequest().toArray(3);
forecas[0].forecast = new float[2]{1,2};
forecas[1].forecast = new float[2]{2,2};
forecas[2].forecast = new float[2]{4,2};
10.Fix this error that JNA gives: Structure.getFieldOrder() on class Something returns names ([field1, field2, ...]) which do not match declared field names ([])
解决方式:You need to make your fields public
所有返回字段需要为公共的
总结
后续问题持续整理
ps: 走过路过给个赞奥!!!