Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JNA找不到函数_Java_C_Dll_Jna_Unsatisfiedlinkerror - Fatal编程技术网

Java JNA找不到函数

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

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.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调用约定。