JNA和DLL对我来说是一个全新的领域......我有一个自定义DLL,它有一个带有此声明的函数:
int myfunc (const char*);
使用以下命令在minGW下编译dll:
>gcc -shared -omydll.dll mydll.c -lgdi32
但是,使用JNA加载它失败,因为它无法在DLL中找到该函数。
public interface mydll extends StdCallLibrary {
mydll INSTANCE = (mydll)Native.loadLibrary("mydll", mydll.class);
int myfunc (String arg);
}
我做了一些研究,似乎这个特殊的错误与DLL函数的调用过程有关。我见过__stdcall
和__cdecl
程序。我还看到许多DLL函数将__declspec(dllexport)
置于其函数声明/实现之前(我不知道这意味着什么或它做了什么)。所以,由于JNA似乎更喜欢__stdcall
程序,现在我的函数看起来像这样:
__declspec(dllexport) int __stdcall myfunc (const char*);
这看起来非常复杂,但并不比我尝试过的任何其他东西都好。使用HashMap添加下划线前缀和@ 4后缀也不起作用:
mydll INSTANCE = (mydll)Native.loadLibrary("mydll", mydll.class, new HashMap () {{
add("myfunc", "_myfunc@4");
}});
JNA文档绝对没有帮助。老实说我不知道我在做什么了。
答案 0 :(得分:2)
原来我正在构建我的DLL就好了,JNA也发现我的DLL也很好;我在确定编译器如何破坏我的符号时出错了。我命名为myfunc
的函数被导出为myfunc@8
或myfunc@32
,具体取决于它们作为参数占用的字节数。这是我在JNA项目中使用的代码:
import java.util.*;
import com.sun.jna.*;
import com.sun.jna.win32.*;
//
public class Test
{
public interface mydll extends StdCallLibrary
{
mydll INSTANCE = Native.loadLibrary("mydll", mydll.class, new HashMap {{
put("myfunc", "myfunc@8");
//Other functions
}});
public int myfunc (long arg);
//Other functions
}
//
public static void main (String[] args)
{
System.out.println
(mydll.INSTANCE.myfunc((long)0x23A3920F)); //Or whatever
return 0;
}
}
我的代码:
#include <windows.h>
#include <stdio.h>
__declspec(dllexport) int __stdcall myfunc (__int64);
/* Other functions */
__declspec(dllexport) int __stdcall myfunc (__int64 arg)
{
/* Whatever */
return return_value;
}
GCC很满意-shared
切换并链接到正确的库,就像我原来的问题一样。 我强烈建议您下载this tool,以便准确了解您的功能名称。
答案 1 :(得分:1)
看看如何构建JNA中的测试库(native / Makefile)。在该示例之后将指示正确的导出签名和调用约定。
__declspec(dllexport)
表示应导出函数名称。
__stdcall
是大多数MS API使用的;你通常没有理由在自己的代码中使用它,因为它只会使链接与其名称的复杂变得复杂。
实际编译(和链接)时,您需要告诉GCC您正在构建共享库。简单地命名文件“* .dll”是不够的。
gcc -o mydll.dll -shared mydll.c
根据您正在访问的本机库,最后可能需要一个或多个-l<libname>
选项。