我正在尝试在 Windows 中将 JNA 与 DLL 一起使用,到目前为止,我能够成功调用一个名为c_aa_find_devices()
. 但是所有功能都以 . 开头,c_aa
我想将其重命名为find_devices()
.
从我收集的方法来看,StdCallFunctionMapper
但我找不到如何在示例中使用它的文档(即如何按名称或序号将 DLL 函数映射到包装的 Java 库接口中的所需名称)。关于文档在哪里的任何建议?
我正在尝试在 Windows 中将 JNA 与 DLL 一起使用,到目前为止,我能够成功调用一个名为c_aa_find_devices()
. 但是所有功能都以 . 开头,c_aa
我想将其重命名为find_devices()
.
从我收集的方法来看,StdCallFunctionMapper
但我找不到如何在示例中使用它的文档(即如何按名称或序号将 DLL 函数映射到包装的 Java 库接口中的所需名称)。关于文档在哪里的任何建议?
A complete working example, using a function mapper.
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<String, String> 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
}
}
使用 StdCallMapper 不会有好处 - 它应该映射那些嵌入了作为名称一部分嵌入的参数的总字节长度的 werid windows std lib 名称。由于它仅对 std lib 完成(只是猜测,但 99% 你的函数并非如此)。
如果您的 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);
所有 JNA 文档都位于主网页、JavaDoc 概述和JavaDocs本身。
上面的示例是正确的想法,因为您需要调整通用 StdCallFunctionMapper 返回的函数名称(假设您使用的是 stdcall 调用约定)。但是, Method.setName() 不存在,如果存在,您也不想调用它。您需要获取 String 结果并将其中的 Java 函数名称替换为目标本机名称,例如
name = super.getFunctionName();
name = name.replace("find_devices", "c_aa_find_devices");
更一般地说,您可以简单地将“c_aa_”前缀添加到返回的名称(或任何前导下划线之后),因为 stdcall 装饰位于名称的末尾。