使用StdCallFunctionMapper在JNA中重命名DLL函数

我正在尝试在Windows中使用JNA和DLL,到目前为止我能够成功调用一个名为c_aa_find_devices()的函数。 但是所有函数都以c_aa ,我想将它重命名为find_devices()

从我收集的方式来看,这是使用StdCallFunctionMapper但我找不到如何在一个示例中使用它的文档(即如何通过名称或序号将DLL函数映射到包装的Java库中的所需名称接口)。 关于文档在哪里的任何建议?

使用StdCallMapper不会做得好 – 它应该映射werid windows std lib名称,这些名称嵌入了作为名称一部分嵌入的参数的总字节长度。 因为它只对std lib做了(只是猜测,但99%你的function不是这样)。

如果你的dll在所有函数上使用了一些公共前缀,你只需要使用类似的东西:

 class Mapper implements FunctionMapper{ public String getFunctionName(NativeLibrary library, Method method) { return GenieConnector.FUNCTION_PREFIX + method.getName(); } } 

GenieConnector.FUNCTION_PREFIX是那个公共前缀。 请记住,我实现了FunctionMapper ,而不是扩展StdCallMapper

从文档中,您需要在原始调用loadLibrary时提供FunctionMapper,以转换名称。 但是,您还需要保留标准调用映射,请尝试以下操作:

 Map options = new HashMap(); options. put( Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionWrapper() { public String getFunctionName(NativeLibrary library, Method method) { if (method.getName().equals("findDevices") method.setName("c_aa_find_devices"); // do any others return super.getFunctionName(library, method); } } ); Native.loadLibrary(..., ..., options); 

一个完整的工作示例,使用函数映射器。

 import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.NativeLibrary; import com.sun.jna.win32.StdCallFunctionMapper; import java.io.File; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class JnaTest { static { Map options = new HashMap(); options. put( Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper() { HashMap map = new HashMap() { { put("testMethod", "testMethod@0"); } }; @Override public String getFunctionName(NativeLibrary library, Method method) { String methodName = method.getName(); return map.get(methodName); } } ); File LIB_FILE = new File("test.dll"); Native.register(NativeLibrary.getInstance(LIB_FILE.getAbsolutePath(), options)); } private static native int testMethod(); public static void main(String[] args) { testMethod(); // call the native method in the loaded dll with the function name testMethod@0 } } 

所有JNA文档都位于主Web页面 , JavaDoc概述和JavaDoc本身。

上面的例子是正确的想法,因为你需要调整通用StdCallFunctionMapper返回的函数名称(假设你正在使用stdcall调用约定)。 但是,Method.setName()不存在,如果有,您不想调用它。 您需要获取String结果并将其中的Java函数名替换为目标本机名,例如

 name = super.getFunctionName(); name = name.replace("find_devices", "c_aa_find_devices"); 

更一般地说,您可以简单地将“c_aa_”前缀添加到返回的名称(或任何前导下划线之后),因为stdcall装饰位于名称的末尾。