Java JNA找不到函数
JNA和DLL对我来说是全新的领域。。。我有一个自定义DLL,它有一个具有以下声明的函数:Java JNA找不到函数,java,c,dll,jna,unsatisfiedlinkerror,Java,C,Dll,Jna,Unsatisfiedlinkerror,JNA和DLL对我来说是全新的领域。。。我有一个自定义DLL,它有一个具有以下声明的函数: int myfunc (const char*); dll在MinGW下使用以下命令编译良好: >gcc -shared -omydll.dll mydll.c -lgdi32 但是,使用JNA加载它失败,因为它在DLL中找不到函数 public interface mydll extends StdCallLibrary { mydll INSTANCE = (mydll)Native.l
int myfunc (const char*);
dll在MinGW下使用以下命令编译良好:
>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函数的调用过程有关。我已经看过\uu stdcall
和\uu cdecl
过程。我还看到许多DLL函数在其函数声明/实现之前放置了\uuu declspec(dllexport)
(我不知道这意味着什么,也不知道它是做什么的)。因此,由于JNA似乎更喜欢\uu 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文档绝对没有帮助。我真的不知道我在做什么。看看JNA中的测试库是如何构建的(原生/生成文件)。下面的示例将指示正确的导出签名和调用约定
\uuu declspec(dllexport)
指示应导出函数名
\uu stdcall
是大多数MS API使用的;通常情况下,您没有理由在自己的代码中使用它,因为它只会因为名称的混乱而使链接复杂化
在实际编译(和链接)时,您需要告诉GCC您正在构建一个共享库。仅将文件命名为“*.dll”是不够的
gcc -o mydll.dll -shared mydll.c
您可能需要一个或多个
-l
选项,具体取决于您正在访问的本机库。结果表明,我构建的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;
}
}
我的c代码:
#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;
}
#包括
#包括
__declspec(dllexport)int uu stdcall myfunc(uu int64);
/*其他职能*/
__declspec(dllexport)int\uu stdcall myfunc(\uu int64 arg)
{
/*随便*/
返回_值;
}
GCC只对
-shared
开关和针对适当库的链接感到满意,就像我最初的问题一样我强烈建议您下载,这样您就可以准确地找到您的函数名。您实际遇到了什么错误?您是否设置了-Djna.library.path=
?您应该提供您看到的实际异常,这将指出问题所在。遵循Java约定,使用大写字母和混合大小写命名类(例如MyDLL.class)。如果您不这么做,则表明您是Java新手,没有真正关注它。除非您有特定的理由,否则不要使用stdcall。如果您确实使用stdcall,您可以通过告诉gcc使用“-Wl,add stdcall alias”包含未修饰的名称来避免函数映射器。JNA提供了一个StdCallFunctionMapper来执行您一直在手动执行的操作,尽管我仍然建议您放弃std调用,改用标准的C调用约定。