JNA无法找到功能

时间:2012-04-24 05:44:10

标签: java c dll jna unsatisfiedlinkerror

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文档绝对没有帮助。老实说我不知道​​我在做什么了。

2 个答案:

答案 0 :(得分:2)

原来我正在构建我的DLL就好了,JNA也发现我的DLL也很好;我在确定编译器如何破坏我的符号时出错了。我命名为myfunc的函数被导出为myfunc@8myfunc@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>选项。