`

JNA调用C实现的DLL

 
阅读更多

(此处以C写的DLL为例子)

第一部分:简单了解DLL里的函数
1
、创建一个动态链接库项目testJNA
2
、在头文件里声明函数

IRIS_SDK_API int STDCALL ik_release_enroll_device (IK_ENROLL_DEVICE_HANDLE dev_handle);
3
、在源码里实现函数

int STDCALL ik_release_enroll_device (IK_ENROLL_DEVICE_HANDLE dev_handle) {

       printf(“。。。。”);

       return 1;

}
4
、生成dll文件:testJNA.dll

5、将要调用的函数所在dll以及这些dll所依赖的dll都拷贝到windows/system32下(一定要将所有依赖的dll都找到,可以到网上下载个工具

 

第二部分:JNA调用DLL的函数

JNA使用一个java接口来代表一个动态链接库发布的所有函数。
对于不需要的原生函数,可以不在java接口中声明java方法原型。

5、定义一个表示链接库的接口如果dll是以stdcall方式输出函数,那么就继承StdCallLibrary。否则就继承默认的Library接口。此接口里定义一个实例 

TestJnaLib INSTANCE = (TestJnaLib)Native.loadLibrary((Platform.isWindows() ? "testJNA.dll" : "c"), TestJnaLib.class);//标蓝的地方一定要这么写

此实例由jna通过反射自动生成。

 

此接口支持在Java端多线程、并发调用本地方法。如果本地类库不是线程安全的,可用

TestJnaLib INSTANCE2 =  Native.synchronizedLibrary(INSTANCE);

来阻止多线程同时访问本地代码。


6
、在表示链接库的接口里定义对应dll里的方法

 

int ik_release_enroll_device(Object devHandle);


7
、调用本地方法

TestJnaLib.INSTANCE.ik_release_enroll_device(devHandle);

 

第三部分:DLL函数对JNA的回调

1dll中定义了如下带回调函数的函数

IRIS_SDK_API int STDCALL ik_init_enroll_module (ik_ipaddress_t   listened_addr,

                                                   int (__stdcall * IK_IDEN_CALLBACK_FUNC)

(IK_IDEN_DEVICE_HANDLE dev_handle// 设备句柄

int type, // 回调类型

void *param); )
红色加粗部分是函数指针。

2
Java部分定义一个回调接口
必须继承自com.sun.jna.Callback接口 (如果回调函数是以stdcall输出,有时候可能引起jvm崩溃,可以改成继承StdCallCallback接口试试,

子接口必须定义单个公有方法或一个名为callback的公有方法。必须持有到回调对象的一个存活引用。一个回调应该不抛出异常。

public interface FunCallBack extends StdCallCallback{

       public int callback(IntByReference devHandle,int type,Pointer para);

}


callback方法里的参数顺序,类型及返回类型必须与C函数的相关类型对应上

3
、定义回调接口的实现

public class CallbackFunImpl implements FunCallBack {

       @Override

       public synchronized int callback(IntByReference devHandle, int type, Pointer para){

      //已知para是指向IkIdenresultArray类型的指针

              IkIdenresultArray ikArray = new IkIdenresultArray(para);

                int count = ikArray.result_count;

                if(ikArray.presult == null || count <= 0){

                    log.info("识别结果数不大于0");

                    return 0;

                }

                IkIdenresult[] rels = (IkIdenresult[])ikArray.presult.toArray(count);

                if (rels == null || rels.length == 0) {

                    log.info("识别结果为空!");

                    return 0;

                }

       }

}

 

上文涉及的结构体的定义如下:

//识别结果列表

    public static class IkIdenresultArray extends Structure{

        public IkIdenresultArray(Pointer p) {

              super(p);

              useMemory(p);

              read();

           }

        

       public IkIdenresultArray() {

           super();

       }

 

       public static class ByReference extends IkIdenresultArray implements Structure.ByReference { }

        public static class ByValue extends IkIdenresultArray implements Structure.ByValue{ }

       

       public IkIdenresult.ByReference presult = new IkIdenresult.ByReference(); // 识别结果列表(表示指针)

        public int result_count ; // 识别结果个数

    }

4
、在表示链接库实现的接口里定义要回调的本地函数

void methodWithCallback(StdCallCallback callback, int left, int right);

本地函数的函数指针用Callback 接口替代。

5
、调用带函数指针的本地函数

TestJnaLib.INSTANCE.methodWithCallback(new CallbackFunImpl(), 4, 6)

最好将标红的地方定义一个static的变量引用它,否则回调函数的内存区域可能被GC回收而引起JVM崩溃,调用如下:

StdCallCallback callback = new CallbackFunImpl();

TestJnaLib.INSTANCE.methodWithCallback(callback, 4, 6)

 

第四部分:JAVAC类型的对应

1、  基本类型的对应可以到网上查找对应表

2、  特殊的struct类型

1>Structure属性传递给本地字段必须是public的。

2>虽然结构体和结构体字段的名字可以是任意的,但他们应该尽可能接近本地定义。参数名及参数顺序对应一样。

3> Structure类的write()方法会把结构体的所有字段固定住,是原生函数可以访问。

4> C语言是不知道你Java的引用的。它只能访问固定的内存地址。因此,在使用JNIJNA时,都会把Java对象锁住。GC不再管理。不删除,也不移动位置。即把传递给Cstruct对象A固定住内存,如果这个A种还嵌套了struct对象,则也被固定住,但是如果嵌套的是struct的引用B,则不会固定,需要把B手动固定,如:

B.ByReference b = new B.ByReference();

b.write();

5> 结构体的定义如:

//识别结果

    public static class IkIdenresult extends Structure{

       //属性都定义为public类型

       public IkIdenresult() {

           super();

       }

       public IkIdenresult(Pointer p) {

           super(p);

           useMemory(p);

           read();

       }

       public static class ByReference extends IkIdenresult implements Structure.ByReference { }//通过ByReference定义的是指针

        public static class ByValue extends IkIdenresult implements Structure.ByValue{ }//通过ByValue定义的是对象

       

        public IntByReference dev_handle; // 识别设备句柄

        public byte []dev_sn = new byte[128];// 设备标志

        public byte []iden_date_time = new byte[32]; // 识别时间

        public int person_id; // personID

        public byte [] person_name= new byte[128]; // 人员姓名

        public int feature_id; // featureID

        public int eye_flag; // 眼睛标志

    }

分享到:
评论

相关推荐

    JNA调用DLL完整实例demo

    在“JNA调用DLL完整实例demo”中,我们首先需要创建一个Java接口,这个接口将代表DLL中的函数。例如,如果DLL中有一个名为`recvWork`的函数,我们的Java接口可能会这样定义: ```java public interface ...

    Jna调用dll实例

    总结来说,JNA调用DLL的关键步骤包括:定义DLL接口,加载DLL,调用DLL函数,并处理可能出现的编码问题。本实例提供了一个具体的应用场景,有助于理解JNA调用DLL的过程,并解决了常见的中文乱码问题。通过学习和实践...

    使用JNA替代JNI调用DLL,并解决内存溢出问题

    在使用JNA调用DLL的过程中,可能会遇到内存溢出的问题。这类问题通常发生在处理大量数据或长时间运行的应用场景中。为了避免这种情况,可以采取以下措施: - **优化数据结构**:合理设计数据结构,减少不必要的数据...

    Android通过JNA调用C,C++方法

    总结,Android通过JNA调用C/C++方法是一个高效且方便的方式,它减少了JNI的繁琐步骤,使Java开发者能更容易地利用C/C++代码。不过,在追求性能或处理复杂数据结构时,可能需要考虑使用JNI。正确理解和使用JNA,可以...

    java用JNA调用dll实例,包含各种参数调用

    本实例将深入探讨如何使用JNA调用DLL,并涵盖了各种参数类型,包括基本数据类型、指针、结构体、回调函数、字符串以及数组。 首先,理解JNA的基本工作原理至关重要。JNA通过映射DLL中的函数到Java类的方法来实现...

    java调用C#封装的dll(jna,com)

    java调用C#封装的dll(jna,com)java调用C#封装的dll(jna,com)java调用C#封装的dll(jna,com)

    jna调用系统dll文件并且获得返回参数的实例

    采用java jna4.1 调用C编写的dll文件,获得返回结果,且获得返回参数的例子

    jna jar实现java调用dll

    通常,这可能是一个测试类或者包含主方法的Java文件,用于演示如何使用JNA调用DLL的具体代码。由于没有详细文件内容,我们将基于JNA的一般用法进行讨论。 在Java中使用JNA调用DLL的基本步骤如下: 1. **添加JNA库*...

    JNA调用.dll文件或.so动态链接库的代码demo

    在标题中提到的“JNA调用.dll文件或.so动态链接库的代码demo”,这是一个实际应用JNA来调用本地动态库的示例。下面我们将深入探讨JNA的工作原理、使用步骤以及如何处理.dll和.so文件。 1. **JNA工作原理**: JNA...

    jna调用C语言函数库dll、so例子

    在"jna调用C jna jni dll"的标签中,我们可以看到这四个关键词。JNA是主要的技术,而"C"代表我们要调用的本地库是用C语言编写的。JNI虽然不是本次讨论的重点,但它是另一种常见的与本地代码交互的方式。"dll"再次...

    自己写的dll文件,用以java jna调用测试用途

    自己写的dll文件,用以java jna调用测试用途自己写的dll文件,用以java jna调用测试用途自己写的dll文件,用以java jna调用测试用途自己写的dll文件,用以java jna调用测试用途

    jna调用C++dll

    Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的原生API...通过学习和实践这个"jna调用C++ dll"的例子,你将能够熟练地处理跨语言的交互,包括处理回调函数这样的高级特性。

    jna调取dll示例demo

    java后端springBoot框架使用jna调取C语言的dll接口(停车场道闸接口) 包含构造体的调用, 回调函数的调用,JNA和C / C ++的数据类型映射,Pointer类型的使用

    c++ 代码实现 dll 工程 用于java jna调用

    2. **Java JNA调用C++ DLL**: - 引入JNA库到Java项目。JNA提供了一种无需编写JNI(Java Native Interface)代码即可调用本地方法的方式。 - 定义C++接口的Java映射类,使用JNA的`Interface`和`Native`类: ```...

    通过JNA让Java调用Dll方法

    研究java调用dll的时候,大部分都是通过jni,比较麻烦,我找到了通过jna方法调用dll的方法,用起来比较方便,只需要引用jna.jar包,这个jar包已经包含在程序中,还包含了我调用dll的遇到难道的解决办法。

    JAVA利用JNA调用DLL

    **JNA 调用DLL步骤** 1. **创建接口**: 创建一个Java接口,声明本地库中的函数签名。每个方法都应使用`native`关键字,并指定适当的返回类型和参数类型。 2. **加载库**: 使用 `Library` 接口的子类,如 `...

    jna调用dll完成demo实例, 超简单

    本实例将详细介绍如何使用JNA调用DLL动态链接库,通过一个超简单的Demo来展示其过程。 首先,我们需要了解JNA的基本工作原理。JNA通过映射Java方法到本地库中的函数,实现了跨语言的通信。在Java中,我们定义一个...

    最简单的JNA调用DLL

    标题中的“最简单的JNA调用DLL”是指Java Native Access(JNA)库在Java程序中调用Windows Dynamic Link Library (DLL) 文件的一种基础方法。JNA是Java平台上的一个开源库,它允许Java代码与本地平台API进行交互,...

    亲测可用,java 成功调用dll函数。包含调用回调函数,springboot版本。最近由于公司业务需要,要调用dll文件,用JNA调用。

    Java通过JNA调用DLL,可以利用C/C++等编写的本地库功能。 3. **回调函数**:在C/C++编程中,回调函数是指被其他函数调用的函数。在Java通过JNA调用DLL时,如果DLL函数需要一个回调函数作为参数,那么Java需要定义一...

    java jna 调用dll例子

    在本例中,“java jna 调用dll例子”指的是使用JNA在Java应用程序中调用Windows上的动态链接库(DLL)文件,这里特别提到了大华SDK的Dll,这通常用于处理视频流和视频播放功能。 大华SDK( Dahua Software ...

Global site tag (gtag.js) - Google Analytics