0
点赞
收藏
分享

微信扫一扫

Java--native方法

灵魂跑者 2022-03-22 阅读 66


简介

说明

        java调用dll动态库的方法,总的有三种:JNI、JNA、JNative。其中JNA调用DLL是最方便的。java使用 JNI来调用dll动态库的调用,工作量略大,一般情况下开发人员会选用JNA或JNative。

        使用JNative调用DLL除了要引入jar包外还需要额外引入一个dll文件,而JNA只需要引入jar即可使用。

官网

​​JNA API​​

数据对照

官网原版

C Type

Native Representation

Java Type

char

8-bit integer

byte

wchar_t

platform-dependent

char

short

16-bit integer

short

int

32-bit integer

int

int

boolean flag

boolean

enum

enumeration type

int (usually)

long long, __int64

64-bit integer

long

float

32-bit floating point

float

double

64-bit floating point

double

pointer (e.g. void*)

platform-dependent (32- or 64-bit pointer to memory)

Buffer

Pointer

pointer (e.g. void*),

array

32- or 64-bit pointer to memory (argument/return)

contiguous memory (struct member)

<P>[] (array of primitive type)

In addition to the above types, which are supported at the native layer, the JNA Java library automatically handles the following types. All but NativeMapped and NativeLong are converted to Pointer before being passed to the native layer.

long

platform-dependent (32- or 64-bit integer)

NativeLong

const char*

NUL-terminated array (native encoding or jna.encoding)

String

const wchar_t*

NUL-terminated array (unicode)

WString

char**

NULL-terminated array of C strings

String[]

wchar_t**

NULL-terminated array of wide C strings

WString[]

void**

NULL-terminated array of pointers

Pointer[]

struct*

struct

pointer to struct (argument or return) (or explicitly)

struct by value (member of struct) (or explicitly)

Structure

union

same as Structure

Union

struct[]

array of structs, contiguous in memory

Structure[]

void (*FP)()

function pointer (Java or native)

Callback

pointer (<T> *)

same as Pointer

PointerType

other

integer type

IntegerType

other

custom mapping, depends on definition

NativeMapped

指针

ByReference类有很多子类,这些类都非常有用

ByteByReference、DoubleByReference、FloatByReference、 IntByReference、LongByReference、 NativeLongByReference、PointerByReference、 ShortByReference、 W32API.HANDLEByReference、X11.AtomByReference、X11.WindowByReference

        ByteByReference等类故名思议,就是指向原生代码中的字节数据的指针。

        PointerByReference类表示指向指针的指针。

        在JNA中模拟指针,最常用到的就是Pointer类和PointerByReference类。Pointer类代表指向任何东西的指针,PointerByReference类表示指向指针的指针。Pointer类更加通用,事实上PointerByReference类内部也持有Pointer类的实例。

示例

C Type

Java Type

void *

Pointer

void **

PointerByReference

char *

Pointer,ByteByReference

char **

PointerByReference

char &

Pointer,ByteByReference

int &

IntByReference

int *

IntByReference

JNA综述

其他网址

Java使用JNA方式调用DLL(动态链接库)(原创,装载请注明出处) - 简书

注意事项

如果dll/so通过x86平台编译,那么只能使用32位jdk环境加载,如果要使用64位jdk,必须使用x64平台编译。

定义接口

public interface Clibrary extends Library 

定义加载dll库文件接口,继承自Library 或StdCallLibrary,默认的是继承Library,如果动态链接库里的函数是以stdcall方式输出的, 那么就继承StdCallLibrary,比如众所周知的kernel32库。

加载动态库

Clibrary INSTANCE = (Clibrary) Native.loadLibrary("VIDEOMP4LIB",Clibrary.class); 

接口内部需要一个公共静态常量:INSTANCE,通过这个常量,就可以获得这个接口的实例,从而使用接口的方法,也就是调用外部dll/so的函数。该常量通过Native.loadLibrary()这个API函数获得,该函数有2个参数:


第一个参数

    动态链接库dll/so的名称,但不带.dll或.so这样的后缀,这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。

    搜索动态链接库路径的顺序是:先从当前类的当前文件夹找,如果没有找到,再在工程当前文件夹下面找win32/win64文件夹,找到后搜索对应的dll文件,如果 找不到再到WINDOWS下面去搜索,再找不到就会抛异常了。

第二个参数

    是本接口的Class类型。JNA通过这个Class类型,根据指定的.dll/.so文件,动态创建接口的实例。该实例由JNA通过反射自动生成。     

    接口中只需要定义你要用到的函数或者公共变量,不需要的可以不定义,注意参数和返回值的类型,应该和链接库中的函数类型保持一致。定义好接口后,就可以使用接口中的函数即相应dll/so中的函数了

    如果本地类库不是线程安全的,可用

Clibrary INSTANCE2 =  (Clibrary)Native.synchronizedLibrary("VIDEOMP4LIB",Clibrary.class);

JNA示例

引入依赖

implementation('net.java.dev.jna:jna:5.5.0')

将dll加入工程

32位dll或so:resources/win32-x86

64位dll或so:resources/win32-x86-64

定义接口与加载

假设本处有个Dll2x64.dll,里边有个加法函数:double Add(double a, double b);

public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("Dll2x64", CLibrary.class);

double Add(double a, double b);
}

调用接口

public class Hello {
public static void main(String[] args) {
System.out.println(CLibrary.INSTANCE.Add(2, 3));
}
}

JNA结构体

必须写结构体成员的顺序及ByReference和ByValue

@Structure.FieldOrder(
{"header", "deviceType"})
public class Device extends Structure {
public byte header; // 头部
public byte deviceType; // 设备类型
public static class ByReference extends Device implements Structure.ByReference{};
public static class ByValue extends Device implements Structure.ByValue{};
)

不写@Structrure.FieldOrder会报异常:finished with non-zero exit value 1 

JNA问题解决

找不到指定模块

log

java.lang.UnsatisfiedLinkError: The specified module could not be found.

原因

缺少库,或者导入错了库

解决方法​(补上缺少的库)

查看缺少的库​:所用软件:Dependency Walker。此软件作用:

  1. 查看 PE 模块的导入模块。
  2. 查看 PE 模块的导入和导出函数。
  3. 动态剖析 PE 模块的模块依赖性。

用法

depends.exe=> File=> Open=> 选择的dll=> 若缺少,会报黄色感叹号(Error Opening file.系统找不到指定文件),例如:

Java--native方法_动态链接库

可以搜索缺少的库,补到工程里。

其他

Exception in thread "main" java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序 

jdk的位数与dll的位数不一致,换成一致的便可。

其他网址

​​JNA调用C语言动态链接库学习实践总结 第2页_Linux编程_Linux公社-Linux系统门户网站​​



举报

相关推荐

0 条评论