java用jna调用C语言dll接口中的回调函数怎么写

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java用jna调用C语言dll接口中的回调函数怎么写相关的知识,希望对你有一定的参考价值。

简单的你会写,那就好办,直接上代码

public interface TestAPI extends StdCallLibrary 

    interface LoginReply extends StdCallCallback 
        /**
         * 登录回调
         */
        void invoke(String userId, long retCode, String retMsg);
    

    /**
     * 注册一个登录回调方法.此方法是dll提供的
     */
    void RegisterLoginReply(LoginReply loginReply);



/**
 * 实现登录回调方法
 */
private class LoginReplyCallBack implements TestAPI.LoginReply 
    @Override
    public void invoke(String userId, long retCode, String retMsg) 
        log.info("登录回调方法:,,", userId, retCode, retMsg);
    


// 设置登录回调
api.RegisterLoginReply(loginReplyCallBack);

参考技术A 用java定一个回调,用jni调你的回调函数 参考技术B

参考这个博客文章

追问

你这个是简单调用,简单调用我都能写,这个回调函数我不知道怎么写

JNA的用法

  JNA(Java Native Access):建立在JNI之上的Java开源框架,SUN主导开发,用来调用C、C++代码,尤其是底层库文件(windows中叫dll文件,linux下是so【shared object】文件)。

  JNI是Java调用原生函数的唯一机制,JNA就是建立在JNI之上,JNA简化了Java调用原生函数的过程。JNA提供了一个动态的C语言编写的转发器(实际上也是一个动态链接库,在Linux-i386中文件名是:libjnidispatch.so)可以自动实现Java与C之间的数据类型映射。从性能上会比JNI技术调用动态链接库要低。

  由于项目中经常要用到java调用so库的情况,这里做一个简单的使用笔记留着回顾。

1、写一个简单的test.c文件:

#include<stdio.h>
int add(int a, int b);
int add(int a, int b)
{
    int c = a + b;
    printf("Hello, this method is used to add two Integer.");
    return c;
}

2、将.c文件编译为so动态链接库

[[email protected] jnaTest]$ gcc -fpic -c test.c 
[[email protected] jnaTest]$ gcc -shared -o libtest.so test.o
[[email protected] jnaTest]$ ll -rlt
total 1140
-rw-rw-r--. 1 keysystem keysystem     162 Apr 21 15:17 test.c
-rw-rw-r--. 1 keysystem keysystem 1146966 Apr 21 15:38 test.jar
-rw-rw-r--. 1 keysystem keysystem    1616 Apr 21 15:46 test.o
-rwxrwxr-x. 1 keysystem keysystem    5940 Apr 21 15:46 libtest.so
[[email protected] jnaTest]$ 

这样就会生成so库文件了。这里so库的命名要为libtest.so,而不能是test.so。因为JNA在找so

3、创建java project,编写Test.java

因为是使用JNA,所以要依赖jna.jar

jna.jar下载地址:http://central.maven.org/maven2/net/java/dev/jna/jna/4.5.1/jna-4.5.1.jar

将jar包引入到项目中

Test.java代码如下:

package jnaTestNew;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;

public class Test {

    public interface CLibraryTest extends Library {
        
        //将so库放到/usr/lib64目录下
        //注意名称要去掉lib前缀和.so的后缀
//        CLibraryTest INSTANCE = (CLibraryTest) Native.loadLibrary("test", CLibraryTest.class);
        
        //将so库放在非系统目录下,以绝对路径的方式引用
        CLibraryTest INSTANCE = (CLibraryTest) Native.loadLibrary("test", CLibraryTest.class, NativeLibrary.getInstance("/home/keysystem/jnaTest/libtest.so").getOptions());
        
        int add(int a, int b);
        
    }
    
    public static void main(String[] args) {
        int a = 6;
        int b = 6;
        
        int c = CLibraryTest.INSTANCE.add(a, b);
        System.out.println("a:" + a);
        System.out.println("b:" + b);
        System.out.println("c为a+b的和:");
        System.out.println("c:" + c);
    }
    
}

其中重点关注so库放置的位置,可以是系统目录即/usr/lib64目录下(64位的操作系统和JDK);

也可以放置在任意可访问路径下,以绝对路径引用,使用方法参见上面的代码。

4、将java Project项目export导出jar包,如test.jar

将jar包放到Linux系统上执行java -jar test.jar

调用情况如下:

[[email protected] jnaTest]$ ll -rlt
total 1140
-rw-rw-r--. 1 keysystem keysystem     162 Apr 21 15:17 test.c
-rw-rw-r--. 1 keysystem keysystem 1146966 Apr 21 15:38 test.jar
-rw-rw-r--. 1 keysystem keysystem    1616 Apr 21 15:46 test.o
-rwxrwxr-x. 1 keysystem keysystem    5940 Apr 21 15:46 libtest.so
[[email protected] jnaTest]$ /home/keysystem/jnaTest
[[email protected] jnaTest]$ java -jar test.jar 
a:6
b:6
c为a+b的和:
c:12
Hello, this method is used to add two Integer.[[email protected] jnaTest]$ 

使用过程中需要注意代码里的so库路径要与so库存放路径一致。

 

以上是关于java用jna调用C语言dll接口中的回调函数怎么写的主要内容,如果未能解决你的问题,请参考以下文章

Java(JNA)传递dll的引用

Atitit.java jna  调用c  c++ dll的原理与实践  总结  v2 &

异步回调函数

C语言的回调函数

jna调用c编写的dll

JNA调用库文件