JNA编程之三:调用自定义的C动态库并支持回调

来源:互联网 发布:炉石秋日 知乎 编辑:程序博客网 时间:2024/04/28 18:49
在文章《JNA编程之一:入门》中已经介绍了如何通过JNA调用Linux系统自带的libc.so动态库的printf函数,现在再通过一个简单的例子介绍如何通过JNA调用自己编写的C动态库并在动态库中调用Java的函数(回调)。

0. 备注:
操作系统:Ubuntu-10.10
工作用户:root
JDK版本:1.6&1.7
开发环境:eclipse

1. 创建C动态库工程JnaCbApi
代码如下:
#include <stdio.h>

//定义回调函数指针
static int (*AddByCallback)(int a,int b)=NULL;

//注册回调函数
void RegisterAdd(int (*callback)(int,int))
{
AddByCallback=callback;
}

//执行回调函数
void DoAddByCallback(int a,int b)
{
int res;
if(AddByCallback==NULL)
{
printf("error: please register the Add function first!\n");
return;
}
res=AddByCallback(a,b);
printf("Java execute add: %d+%d=%d\n",a,b,res);
}
说明:
1)动态库JnaCbApi的主要功能是由外部应用程序注册一个回调函数,然后调用该回调函数进行加法运算。因此外部应用程序的回调函数必须实现两个整数的加法运算。
2)该动态库只留出了两个接口函数RegisterAdd和DoAddByCallback。其中RegisterAdd用于注册一个Java的回调函数,而DoAddByCallback则调用Java注册的回调函数进行加法运算,并将运算结果打印出来。
3)编译链接生成 libJnaCbApi.so动态库文件。

2. 往Java工程JnaTest中添加新代码
注:JnaTest工程是在《JNA编程之一:入门》一文中创建的。
2.1 往JnaTest工程中添加新的源文件JnaCallback.java,并在文件中输入如下代码:
package myjava.jna.test;

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

public class JnaCallback
{
//定义接口CLibrary,继承自com.sun.jna.Library
    public interface CLibrary extends Library
    {
     //定义接口JavaCallbackAdd,继承自com.sun.jna.Callback
     interface JavaCallbackAdd extends Callback
     {
     int CallbackAdd(int a,int b);
     }
     //动态库的函数声明
     void RegisterAdd(JavaCallbackAdd callback);
     void DoAddByCallback(int a,int b);
    }
 
    public static void main(String[] args)
    {
     //接口实例化并初始化实例
     CLibrary lib = (CLibrary)Native.loadLibrary("JnaCbApi",CLibrary.class);
     CLibrary.JavaCallbackAdd callback=new CLibrary.JavaCallbackAdd()
{
             //实现CallbackAdd函数
public int CallbackAdd(int a,int b)
{
return a+b;
}
};
//调用动态库的函数
lib.RegisterAdd(callback);
//由动态库执行CallbackAdd回调函数
lib.DoAddByCallback(1,2);
    }
}

2.2 复制动态库文件libJnaCbApi.so到JnaTest工程根目录下。

2.3 编译JnaCallback.java文件并运行,结果如图2-1所示。
JNA编程之三:调用自定义的C动态库并支持回调 - Jim - Jim Liang
图2-1:JnaCallback运行结果
 
提示:如果在你的Linux环境下JnaCallback程序无法加载libJnaCbApi.so动态库,通常有两种解决办法。
1)将libJnaCbApi.so复制到系统的动态库目录,如 /lib 或 /usr/lib。
2)修改/etc/profile文件,在文件末尾添加命令:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./,保存后注销或重启系统即可。添加这句命令的意思是让系统支持从“当前目录”加载动态库。

【参考】:
1)https://github.com/twall/jna/blob/master/www/CallbacksAndClosures.md
2)http://hpfgc.blog.163.com/blog/static/14799557201011814356333/
0 0
原创粉丝点击