我正在开发一个在Windows和Linux上运行的java项目,并且我正在使用第三方共享库,这两个操作系统都有相同的方法签名。 但是,dll的调用约定是stdcall,而共享对象是cdecl。
我想避免重复的callback代码,两个接口和两个类,每个调用约定一个接口。 我想为callback函数编写一个单一的代码。 那可能吗?
在linux下访问.so的代码中唯一的变化就是界面。 callback函数代码本身是相同的。 我会感激任何消化。
import com.sun.jna.Callback; interface IExternLibCallback extends Callback {..}
这是我为dll中的callback编写的代码:
//Interface to stdcall (Windows) package test1; import com.sun.jna.win32.StdCallLibrary; interface IExternLibCallback extends StdCallLibrary.StdCallCallback { void callback (JEventDataStructure context_data); } //Class that implements the interface package test1; class ExternLibCallback implements IExternLibCallback { ... Other class codes go here .... @ Override public void callback (JEventDataStructure contextData) { ... Code of callback function } }
谢谢,
费尔南多
您可以使用StdCallLibrary / StdCallCallback来声明它们,但可能不会在所有平台上定义该行为。 在不支持其他调用约定的平台(这是除了win32之外的所有东西)上,该选项被忽略,但并不一定在所有平台上都经过测试。
这是首选的定义,它只为Windows定义stdcall库。
interface MyLibrary extends Library { interface MyCallback extends Callback { public void invoke(); } void callbackFunction(MyCallback cb); MyLibrary INSTANCE = (MyLibrary)Native.loadLibrary("mylib", Platform.isWindows() ? MyWin32Library.class : MyLibrary.class); } interface MyWin32Library extends MyLibrary, StdCallLibrary { interface MyStdCallCallback extends MyCallback, StdCallCallback {} void callbackFunction(MyStdCallCallback cb); }
如果你只是针对linux和windows,那么一个接口就足够了(尽管如此我建议你测试一下):
interface MyLibrary extends StdCallLibrary { interface MyCallback extends StdCallCallback { public void invoke(); } void callbackFunction(MyCallback cb); MyLibrary INSTANCE = (MyLibrary)Native.loadLibrary("mylib", MyLibrary.class); }
我会有另一个JNAWrapper的包装。 所以例如,如果为DLL的JNA包装被称为IExternLibWindows
和Linux的一个被称为IExternLibLinux
,我会写另一个包装 – IExternLib
。 然后,
public interface IExternLibWindows extends StdCallLibrary{ public IExternLibWindows Instance ; ... void stdcall_somefunc(...); ... } public interface IExternLibLinux extends StdCallLibrary{ public IExternLibLinux Instance ; ... void cdecl_somefunc(...); ... } public class IExternLib(){ public void somefunc(...){ if(System.getProperty("os.name").startsWith("Windows")) IExternLibWindows.stdcall_somefunc(...); else if(System.getProperty("os.name").startsWith("Linux")) IExternLibLinux.cdecl_somefunc(...); } }