简体   繁体   English

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

[英]how to isolate JNA bindings that are platform specific?

I have a project where I defined a JNA wrapper to Windows kernel32 library, upon which I have made several helpers that are not critical for the project but increase the integration to the platform (namely: system debug logging with OutputDebugString + DebugView and Mailslot messaging features). 我有一个项目,其中定义了Windows kernel32库的JNA包装器,在该项目上我做了几个对项目不重要的助手,但增加了对该平台的集成(即:使用OutputDebugString + DebugView和Mailslot消息传递功能进行系统调试日志记录)。

Here is my JNA defines: 这是我的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
    //...

}

And the Mailslot definition: 和邮筒的定义:

public class Mailslot {

    static JnaKernel32 kernel32 = JnaKernel32.INSTANCE;
    boolean localMailslot = false;
    int lastError = 0;

    private int hMailslot = JnaKernel32.INVALID_HANDLE_VALUE;

    //...
}

And in some places I have also 在某些地方,我也

static JnaKernel32 kernel32 = JnaKernel32.INSTANCE; //to call OutputDebugString
//...
kernel32.OutputDebugString("some debug message");

My concern is that project could be used also on GNU/Linux or MacOS X but obviously the Native.loadLibrary fails at runtime if executed on eg OSX. 我担心的是,该项目可以在GNU / Linux或MacOS X上使用,但是如果在例如OSX上执行, Native.loadLibrary显然会在运行时失败。

I am considering about 我正在考虑

  • either porting the native feature with other JNA binding 要么将本机功能与其他JNA绑定一起移植
  • or simply disable the existing Windows kernel32 binding when running on another platform as it is just convenient but not mandatory helpers. 或者在其他平台上运行时直接禁用现有的Windows kernel32绑定,因为这很方便,但不是必需的帮助程序。

How can I isolate the platform-specific features and calls that are made? 如何隔离平台特定的功能和进行的调用? I was thinking about moving the JNA part to a runtime loaded plugin perhaps? 我正在考虑将JNA部件移动到运行时加载的插件中吗?

The answer is really a general software development strategy. 答案确实是一种通用的软件开发策略。

  1. Identify the API that your client code needs 确定您的客户端代码需要的API

    In this case, it might be MailsSlot.sendMessage(int destID, String msg) 在这种情况下,它可能是MailsSlot.sendMessage(int destID, String msg)

  2. Abstract the implementation details behind that API 摘要该API背后的实现细节

    public interface MailSlot { void sendMessage(int destId, String msg); }

  3. Provide one or more concrete implementations to meet the API contract 提供一种或多种具体的实现方式以符合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 } }

    Choose the appropriate implementation at runtime: 在运行时选择适当的实现:

    MailSlot mslot = Platform.IS_WINDOWS ? new Win32MailSlot() : new OSXMailSlot();

After a few implementations, you may find some duplicated code, which you might then refactor into an abstract base class shared among the platform-specific implementations. 在执行了几次之后,您可能会发现一些重复的代码,然后可以将它们重构为特定于平台的实现之间共享的抽象基类。

See the JNA platform FileUtils class for an example of such an strategy. 有关此类策略的示例,请参见JNA平台FileUtils类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM