最近的项目中用到了c++回调java,试了很多方法,有通过jni的方式,也有jna的方式,jni复杂很多,相反jna就简单不少,jna为jnative,JNative 可以让你方便的访问 Windows 平台下的 DLL 以及 Linux 平台下的 so 动态连接库文件,无需在编写一行 C/C++ 代码,JNative 是动态的。下面是我的测试demo。
1、首先建立一个动态库文件,这里用vs2005.新建一个dll工程即可。下面是dll工程需要的两个文件
JNativeTest.h:为头文件,申明dll中的导出函数。这里申明了一个函数指针(pfCallbackTest)和一个导出函数(RegCallback)
#ifndef JNativeTes_H
#define JNativeTes_H
#ifdef JNATIVETEST_EXPORTS
#define JNATIVETEST_API extern "C" __declspec(dllexport)
#else
#define JNATIVETEST_API __declspec(dllimport)
#endif
typedef void (*pfCallbackTest)(char * msg, char* data, int type); /*回调函数声明*/
JNATIVETEST_API void RegCallback(pfCallbackTest ev, char *msg, char *data, int type);
#endif
JNativeTest.cpp:为实现文件,在cpp文件中实现了导出函数,在函数中调用了回调函数
#include "JNativeTest.h"
#include "stdio.h"
/*注册回调*/
void RegCallback(pfCallbackTest ev, char *msg, char *data, int type)
{
ev(msg, data, type);
printf("callbackcallback\n");
}
编译,即可生成dll文件。
3、下载jnative:http://sourceforge.net/projects/jnative/files/
2、下载好后是个jar文件,导入到eclipse工程中,添加java代码,一个是回调类的代码,一个测试代码
TestCallback.java:回调类代码,回调类要实现Callback接口,并实现Callback的两个方法,一个是callback,这个是用来获取回调函数的参数,并在此方法中
实现自己的业务逻辑,这个方法相当于回调函数。另一个需要实现的抽象接口是getCallbackAddress,这个方式可以获取回调函数的地址,在调用c++中的接口测试的时候,需要传入回调函数的函数指针,就可以把getCallbackAddress获取的函数地址传进去。另外,要把dll文件拷贝到java工程的目录中,这样jnative才能找到此dll。
package TestCallback;
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.pointers.*;
import org.xvolks.jnative.util.Callback;
/**
* @date 2009-3-17
* @author charis
* @Copyright (c) qqtech All rights reserved. http://www.qqtech.com
*/
public class TestCallback implements Callback/* 实现此接口 */{
public TestCallback() {
}
/**
* Method callback java对应于dll中的回调函数
*
* @param values
* an long[] 参数数组,非整型数代表的都是地址
* @return an int
* @version 3/17/2008
*/
public int callback(long[] values) {
if (values == null) {
System.err.println("callback ret " + 3);
return 3;
}
if (values.length == 3) {
String name = "";
try {
Pointer _pointer = Pointer.createPointerToNativeMemory(
(int) values[0], 100); /* 获取字符串通过指针 */
Pointer _pointer1 = Pointer.createPointerToNativeMemory(
(int) values[1], 100);
name = _pointer.getAsString() + "\n" + _pointer1.getAsString();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.err.println(name + "\n" + values[2]);
return 1;
} else {
System.err.println("Bad number of arguments ! 3 expected "
+ values.length + " found");
System.err.println("callback ret " + 2);
return 2;
}
}
/**
* java回调函数地址
*/
public int getCallbackAddress() throws NativeException {
return JNative.createCallback(3/* 回调函数参数数目 */, this);
}
}