JNative(http://sourceforge.net/projects/jnative/)是供java直接调用c++dll的工具包,这样java程序员仅仅知道c++dll中的函数名和参数类型就可以直接调用dll 了,省去了使用JNI的繁琐。
下面是一个使用c++dll回调函数的例子:
dll名字JNativeTest.dll
C++代码:
JNativeTest.h:
- #ifndef JNativeTes_H
- #define JNativeTes_H
- /** The following ifdef block is the standard way of creating macros which make exporting
- * from a DLL simpler. All files within this DLL are compiled with the JNATIVETEST_EXPORTS
- * symbol defined on the command line. this symbol should not be defined on any project
- * that uses this DLL. This way any other project whose source files include this file see
- * JNATIVETEST_API functions as being imported from a DLL, wheras this DLL sees symbols
- * defined with this macro as being exported.
- **/
- #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); /*回调函数声明*/
- // This class is exported from the JNativeTest.dll
- JNATIVETEST_API char* fnJNativeTest(char* msg);
- JNATIVETEST_API void RegCallback(pfCallbackTest ev);
- #endif
#ifndef JNativeTes_H
#define JNativeTes_H
/** The following ifdef block is the standard way of creating macros which make exporting
* from a DLL simpler. All files within this DLL are compiled with the JNATIVETEST_EXPORTS
* symbol defined on the command line. this symbol should not be defined on any project
* that uses this DLL. This way any other project whose source files include this file see
* JNATIVETEST_API functions as being imported from a DLL, wheras this DLL sees symbols
* defined with this macro as being exported.
**/
#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); /*回调函数声明*/
// This class is exported from the JNativeTest.dll
JNATIVETEST_API char* fnJNativeTest(char* msg);
JNATIVETEST_API void RegCallback(pfCallbackTest ev);
#endif
JNativeTest.cpp :
- // JNativeTest.cpp : Defines the entry point for the DLL application.
- #include <windows.h>
- #include "JNativeTest.h"
- BOOL APIENTRY DllMain( HANDLE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
- pfCallbackTest fCallbackTest = NULL;
- /*注册回调*/
- void RegCallback(pfCallbackTest ev)
- {
- fCallbackTest = ev;
- }
- // This is an example of an exported function.
- char* fnJNativeTest(char* msg)
- {
- if (fCallbackTest != NULL)
- fCallbackTest(msg, "Test", 6); /*调用回调函数*/
- return msg;
- }
// JNativeTest.cpp : Defines the entry point for the DLL application.
#include <windows.h>
#include "JNativeTest.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
pfCallbackTest fCallbackTest = NULL;
/*注册回调*/
void RegCallback(pfCallbackTest ev)
{
fCallbackTest = ev;
}
// This is an example of an exported function.
char* fnJNativeTest(char* msg)
{
if (fCallbackTest != NULL)
fCallbackTest(msg, "Test", 6); /*调用回调函数*/
return msg;
}
java代码:
TestCallback.java
- 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() + "/" + _pointer1.getAsString();
- } catch (Exception e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- System.err.println("lParam " + name + "/" + 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);
- }
- }
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() + "/" + _pointer1.getAsString();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.err.println("lParam " + name + "/" + 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);
}
}
TestMain.java
- import org.xvolks.jnative.JNative;
- import org.xvolks.jnative.Type;
- /**
- * @date 2009-3-10
- * @author charis
- * @Copyright (c) qqtech All rights reserved. http://www.qqtech.com
- */
- public class TestMain{
- public TestMain(){
- }
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- try {
- JNative termcallback = new JNative("JNativeTest.dll", "RegCallback" /*函数名*/ );
- TestCallback _callback = new TestCallback();
- termcallback.setRetVal(Type.VOID);
- termcallback.setParameter(0, _callback.getCallbackAddress()); /*回调函数地址作为参数传递到dll*/
- /**
- * 调用getCallbackAddress后要调用该行代码
- */
- JNative.releaseCallback(_callback);
- termcallback.invoke(); /*注册回调函数*/
- JNative term = new JNative("JNativeTest.dll", "fnJNativeTest"/*函数名*/);
- term.setRetVal(Type.STRING); /*返回值类型*/
- term.setParameter(0, "hello word!"); /*左起第一个参数,索引为0*/
- term.invoke();
- String value = term.getRetVal();
- System.out.println(value);
- term.setParameter(0, "hello word second!");
- term.invoke();
- value = term.getRetVal();
- System.out.println(value);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.Type;
/**
* @date 2009-3-10
* @author charis
* @Copyright (c) qqtech All rights reserved. http://www.qqtech.com
*/
public class TestMain{
public TestMain(){
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
JNative termcallback = new JNative("JNativeTest.dll", "RegCallback" /*函数名*/ );
TestCallback _callback = new TestCallback();
termcallback.setRetVal(Type.VOID);
termcallback.setParameter(0, _callback.getCallbackAddress()); /*回调函数地址作为参数传递到dll*/
/**
* 调用getCallbackAddress后要调用该行代码
*/
JNative.releaseCallback(_callback);
termcallback.invoke(); /*注册回调函数*/
JNative term = new JNative("JNativeTest.dll", "fnJNativeTest"/*函数名*/);
term.setRetVal(Type.STRING); /*返回值类型*/
term.setParameter(0, "hello word!"); /*左起第一个参数,索引为0*/
term.invoke();
String value = term.getRetVal();
System.out.println(value);
term.setParameter(0, "hello word second!");
term.invoke();
value = term.getRetVal();
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意 :
当调用dll回调函数失败时,请检查参数数目和参数类型,并请c++程序员核对dll中回调函数的声明。
如此typedef void (WINAPI *pfCallbackTest)(char * msg, char* data, int type)声明将会引起调用失败
原文链接:http://hi.baidu.com/chinacharis/blog/item/87ef7f00b0b092067bec2cfb.html