6

我正在尝试在 Windows 中将 JNA 与 DLL 一起使用,到目前为止,我能够成功调用一个名为c_aa_find_devices(). 但是所有功能都以 . 开头,c_aa我想将其重命名为find_devices().

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

4

4 回答 4

6

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
    }


}
于 2016-02-24T20:19:01.177 回答
4

使用 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

于 2009-05-12T21:40:41.857 回答
2

从文档中,您需要在对转换名称的 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);
于 2009-02-05T23:27:15.727 回答
1

所有 JNA 文档都位于主网页JavaDoc 概述JavaDocs本身。

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

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

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

于 2009-05-12T15:35:40.097 回答