Java 如何隔离特定于平台的JNA绑定?

Java 如何隔离特定于平台的JNA绑定?,java,windows,macos,jna,multiplatform,Java,Windows,Macos,Jna,Multiplatform,我有一个项目,在该项目中,我定义了一个Windows内核32库的JNA包装器,在此基础上,我制作了一些辅助工具,这些辅助工具对该项目来说并不重要,但增加了与平台的集成(即:具有OutputDebugString+DebugView和Mailslot消息传递功能的系统调试日志记录) 以下是我的JNA定义: import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import com.sun.jna.N

我有一个项目,在该项目中,我定义了一个Windows内核32库的JNA包装器,在此基础上,我制作了一些辅助工具,这些辅助工具对该项目来说并不重要,但增加了与平台的集成(即:具有
OutputDebugString
+DebugView和Mailslot消息传递功能的系统调试日志记录)

以下是我的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
显然会在运行时失败

我正在考虑

  • 将本机功能与其他JNA绑定一起移植
  • 或者,在另一个平台上运行时,只需禁用现有的Windows内核32绑定,因为这只是一种方便,而不是强制帮助

如何隔离特定于平台的功能和调用?我在考虑将JNA部分转移到运行时加载的插件上,也许?

答案实际上是一种通用的软件开发策略

  • 确定客户端代码所需的API

    在本例中,它可能是
    MailsSlot.sendMessage(int destID,String msg)

  • 抽象该API背后的实现细节

    公共接口邮箱{
    void sendMessage(int destId,字符串msg);
    }

  • 提供一个或多个具体实现以满足API合同的要求

    公共类Win32MailSlot实现MailSlot{
    public void sendMessage(int destId,String msg){
    //在这里做一些特定于windows的事情
    }
    }

    public类OSXMailSlot实现MailSlot{
    public void sendMessage(int destId,String msg){
    //在这里做一些特定于windows的事情
    }
    }

    在运行时选择适当的实现:

    MailSlot mslot=Platform.IS\u WINDOWS?新建Win32MailSlot():新建OSXMailSlot()

  • 在一些实现之后,您可能会发现一些重复的代码,然后您可能会将这些代码重构为平台特定实现之间共享的抽象基类

    有关这种策略的示例,请参见JNA平台类