`
longgangbai
  • 浏览: 7249895 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多

        如何通过JNA调用Linux系统自带的libc.so动态库的printf函数,现在再通过一个简单的例子介绍如何通过JNA调用自己编写的C动态库并在动态库中调用Java的函数(回调)。

 编写C代码:

#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.编译C代码:

gdyt:/home/yc/soft/test # ll
total 36
-rwxr-xr-x 1 root root  5812 Dec 22 23:14 libtest.so
-rw-r--r-- 1 root root    61 Dec 22 23:14 test.c
-rw-r--r-- 1 root root   367 Dec 22 23:17 testcallback.c
-rwxr-xr-x 1 root root 19584 Dec 22 23:14 testlib.c
gdyt:/home/yc/soft/test # gcc -fPIC -shared testcallback.c -o libtestcallback.so
gdyt:/home/yc/soft/test # ll
total 48
-rwxr-xr-x 1 root root  5812 Dec 22 23:14 libtest.so
-rwxr-xr-x 1 root root  9887 Dec 22 23:19 libtestcallback.so
-rw-r--r-- 1 root root    61 Dec 22 23:14 test.c
-rw-r--r-- 1 root root   367 Dec 22 23:17 testcallback.c
-rwxr-xr-x 1 root root 19584 Dec 22 23:14 testlib.c

 

3.查看so并拷贝到lib目录

 

查看so的依赖关系

gdyt:/home/yc/soft/test # ldd libtestcallback.so
        linux-vdso.so.1 =>  (0x00007fff24dfe000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fc91c7ea000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc91cd78000)

 

添加相关的连接

gdyt:/home/yc/soft/test # ln -s  libtestcallback.so libJnaCbApi.so.6


gdyt:/home/yc/soft/test # ll
total 48
lrwxrwxrwx 1 root root    18 Dec 22 23:24 libJnaCbApi.so.6 -> libtestcallback.so
-rwxr-xr-x 1 root root  5812 Dec 22 23:14 libtest.so
-rwxr-xr-x 1 root root  9887 Dec 22 23:19 libtestcallback.so
-rw-r--r-- 1 root root    61 Dec 22 23:14 test.c
-rw-r--r-- 1 root root   367 Dec 22 23:17 testcallback.c
-rwxr-xr-x 1 root root 19584 Dec 22 23:14 testlib.c

查看相关的依赖关系
gdyt:/home/yc/soft/test # ldd libJnaCbApi.so.6
        linux-vdso.so.1 =>  (0x00007fffe95ff000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fb9e101d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fb9e15ab000)

 

4.拷贝到lib目录

gdyt:/home/yc/soft/test # cp libtestcallback.so  lib/

 

5.编写Java代码:

package com.etrip;

import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
/**
 * 
 * @Title: TODO
 * @Description: 实现TODO
 * @Copyright:Copyright (c) 2011
 * @Company:
 * @Date:2012-12-22
 * @author longgangbai
 * @version 1.0
 */
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);
		if(lib!=null){
			System.out.println("JnaCbApi加载成功...");
		}
		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);
	}
}

 

提示:如果在你的Linux环境下JnaCallback程序无法加载libJnaCbApi.so动态库,通常有两种解决办法。
1)将libJnaCbApi.so复制到系统的动态库目录,如 /lib 或 /usr/lib。
2)修改/etc/profile文件,在文件末尾添加命令:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./,保存后注销或重启系统即可。添加这句命令的意思是让系统支持从“当前目录”加载动态库。


 

6.测试

 

【参考】:
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics