【问题标题】:JNA and C++ - Minimalistic Example resulting in UnsatisfiedLinkErrorJNA 和 C++ - 导致 UnsatisfiedLinkError 的简约示例
【发布时间】:2016-04-25 16:19:06
【问题描述】:

对于我当前的项目,我需要在我的 java 应用程序中使用一些 c++ 代码。在我看来,常见的解决方案是从 c++ 部分创建一个 DLL 并通过 JNA 访问它。由于我是 C++ 的初学者,我认为我从最低限度的基础开始,然后从那里继续工作。但是我什至无法运行这些最小的示例。这是我所做的:

我使用 Visual Studio 的文档来创建我的 DLL(可在此处找到:https://msdn.microsoft.com/de-de/library/ms235636.aspx

你所做的是定义一个标题

// MathFuncsDll.h

#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport) 
#else
#define MATHFUNCSDLL_API __declspec(dllimport) 
#endif
namespace MathFuncs
{
 // This class is exported from the MathFuncsDll.dll
 class MyMathFuncs
 {
 public: 
    // Returns a + b
    static MATHFUNCSDLL_API double Add(double a, double b); 
 };
}

和一个 .cpp 文件

// MathFuncsDll.cpp : Defines the exported functions for the DLL application.

#include "stdafx.h"
#include "MathFuncsDll.h"
#include <stdexcept>

using namespace std;

namespace MathFuncs
{
 double MyMathFuncs::Add(double a, double b)
 {
    return a + b;
 }
}

然后将其构建为 DLL。到目前为止,这没有错误。 然后我开始编写一个小的 Java 程序来通过 JNA 访问这个 DLL,再次坚持 JNA 文档:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {

  // This is the standard, stable way of mapping, which supports extensive
  // customization and mapping of Java to native types.

  public interface CLibrary extends Library {
      CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "zChaffDLL" : "c"), CLibrary.class);

      double Add(double a, double b);
  }

  public static void main(String[] args) {
      CLibrary.INSTANCE.Add(5d, 3d);

  }
}

运行此程序会导致此错误: 线程“main”java.lang.UnsatisfiedLinkError 中的异常:查找函数“Add”时出错:找不到指定的过程。

我修改了一下,但无法解决问题。在这一点上,我几乎迷路了,因为我看不到自己能够构建一个更简单的例子 - 所以任何帮助或指针都会非常感激。

【问题讨论】:

  • C++ 和 C 有不同的接口 (ABI),事实上你正在加载一个 CLibrary 类型的 C++ 库,这对我来说已经很可疑了。另请参阅:Java Native Access doesn't do C++, right?。改用 JNI 可能会更好,但工作量更大。

标签: java c++ dll jna


【解决方案1】:

C++ 根据编译器的突发奇想“修改”导出的名称。例如,“void main(argc, argv)”可能会显示为“_Vmain_IPP@xyzzy”。

在您的 DLL 上运行 depends.exe 以查看导出名称的样子。 extern "C" 在您的代码中将阻止 C++ 修改导出的函数名称。

JNA 可以很好地处理静态函数; JNAerator 自动适应一些额外的修饰,但如果你想将 C++ 类映射到 Java 类,你最好使用 SWIG 之类的东西。

【讨论】:

  • 我尝试使用 extern "C" 但没有帮助。 depends.exe 显示正确的函数名称,但有一个?在他们面前。到目前为止,我无法弄清楚为什么会这样
  • 在您的问题中显示更新的源代码和depends.exe 输出。
猜你喜欢
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多