我有一个项目,我在其中定义了一个JNA包装到Windows kernel32库,在这个库上我做了几个对项目不重要的帮助程序,但增加了与平台的集成(即:使用OutputDebugString
+ DebugView和Mailslot消息传递function)。
这是我的JNA定义:
import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import com.sun.jna.Native; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.W32APIFunctionMapper; import com.sun.jna.win32.W32APITypeMapper; public interface JnaKernel32 extends StdCallLibrary { //StdCall is needed for lib kernel32 @SuppressWarnings("unchecked") Map ASCII_OPTIONS = new HashMap(){ { put(OPTION_TYPE_MAPPER, W32APITypeMapper.ASCII); put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.ASCII); } }; @SuppressWarnings("unchecked") Map UNICODE_OPTIONS = new HashMap(){ { put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); } }; Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS; JnaKernel32 INSTANCE = (JnaKernel32) Native.loadLibrary("kernel32", JnaKernel32.class, DEFAULT_OPTIONS); //some system defines //... }
和邮筒的定义:
public class Mailslot { static JnaKernel32 kernel32 = JnaKernel32.INSTANCE; boolean localMailslot = false; int lastError = 0; private int hMailslot = JnaKernel32.INVALID_HANDLE_VALUE; //... }
而且在一些地方我也有
static JnaKernel32 kernel32 = JnaKernel32.INSTANCE; //to call OutputDebugString //... kernel32.OutputDebugString("some debug message");
我担心的是该项目也可以在GNU / Linux或MacOS X上使用,但显然如果在OSX上执行,则Native.loadLibrary
在运行时Native.loadLibrary
失败。
我正在考虑
如何隔离特定于平台的function和调用? 我正在考虑将JNA部分移动到运行时加载的插件?
答案实际上是一个通用的软件开发策略。
确定您的客户端代码需要的API
在这种情况下,它可能是MailsSlot.sendMessage(int destID, String msg)
抽象该API背后的实现细节
public interface MailSlot { void sendMessage(int destId, String msg); }
提供一个或多个具体实现来满足API合同
public class Win32MailSlot implements MailSlot { public void sendMessage(int destId, String msg) { // Do stuff here that's windows-specific } }
public class OSXMailSlot implements MailSlot { public void sendMessage(int destId, String msg) { // Do stuff here that's windows-specific } }
在运行时选择适当的实现:
MailSlot mslot = Platform.IS_WINDOWS ? new Win32MailSlot() : new OSXMailSlot();
经过几次实现之后,您可能会发现一些重复的代码,然后您可能会重构成在特定于平台的实现中共享的抽象基类。
请参阅JNA平台的FileUtils
类以获取此类策略的示例。