【问题标题】:Calling C++ dll from Java从 Java 调用 C++ dll
【发布时间】:2012-02-28 16:36:19
【问题描述】:

我正在为一个小型应用程序使用 Java。它是对现有 MFC 项目的重写。我需要更改一个现有的 dll 以启用使用 JNI 从 Java 进行访问。所有这些 Java 东西对我来说都是新的,所以当我阅读其他论坛帖子时,我遇到了一些麻烦并且感觉相当密集。在现有的 dll 中,我有一个这样的函数:

extern "C" __declspec(dllexport) bool Create()
{
     return TRUE;
}

愚蠢的提问时间。如何正确设置它以由 Java 调用?

我试过了:

JNIEXPORT jboolean JNICALL Create()
{
     return TRUE;
}

我包括 jni.h 并且一切编译正常。但是,当我从 Java 调用它时,我得到 UnsatisfiedLinkError。我使用这个从 Java 调用它:

public static native boolean CreateSession();

System.load("D:\\JavaCallTest.dll");
Create();

有人可以将我推向正确的方向吗?我真诚地感谢任何帮助。

谢谢,

尼克

【问题讨论】:

  • 另外,您可以使用 JNA 而不是 JNI,因为您有一个可以由 JNA 加载的 C dll。
  • 请贴出抛出的异常...
  • 使用 javah 生成 C 头文件,正如 Jörn Horstmann 在下面提到的那样——或者完全避免使用 JNI。一个简单的替代方案是 JNA。
  • 感谢您的帮助。我曾考虑过使用 JNA,但我想将任何额外的东西保持在最低限度,所以我认为我最好使用 JNI。

标签: java dll java-native-interface


【解决方案1】:

您需要在本机代码中包含 Java 类名和路径,例如,如果您的本机方法在 Java 中声明为:

public class NativeCode {
    public static native boolean CreateSession();
}

并且类路径是(例如)com.example.NativeCode,您将在本机中声明您的方法,如下所示:

extern "C"
JNIEXPORT jboolean JNICALL Java_com_example_NativeCode_CreateSession(JniEnv* env, jclass clazz)
{
    return JNI_TRUE;
}

所有 JNI 方法都有一个 JNIEnv 指针和类作为它们的前两个参数。

【讨论】:

  • 就是这样。它现在似乎正在工作。当我不处理这样一个简单的函数时,我们会看到我遇到了什么样的问题。感谢您的帮助。
  • @GooseSerbus 使用的参数怎么样 public static native boolean CreateSession(?,?);
  • @Aniket 参数被添加到 C 方法中的参数上,例如:public static native boolean CreateSession(boolean, Object); 将是 JNIEXPORT jboolean JNICALL Java_com_example_NativeCode_CreateSession(JniEnv* env, jclass clazz, jboolean b, jobject o)
【解决方案2】:

静态原生方法至少还需要两个参数:

JNIEnv *env
jclass clazz

函数名也要与java包结构相对应。

JNIEXPORT jboolean JNICALL Java_com_example_CreateSession(JNIEnv *env, jclass clazz)

理想情况下,您将使用javah 工具从声明本机方法的java 类创建一个头文件,然后实现声明的函数原型。

【讨论】:

  • +1 提到应该使用 javah 来生成函数签名。
  • 找到这个 (stackoverflow.com/a/3452258/978528) 并设置 Eclipse 以运行 javah。现在工作很好。现在我必须实现其余的东西。希望是直截了当的。
【解决方案3】:

我有一个类似的问题 - 我需要从 Java 访问一个现有的 C 代码库。熟悉SWIG 让我受益匪浅,这是一个生成中间 C++ DLL(调用 C 代码)的工具,以及调用 C++ DLL 的 Java 代码。

如果您要包装的 DLL 函数不止 1 个,不妨试试这个工具,否则您必须熟悉 JNI...

编辑

System.load() 调用似乎找不到您的 DLL。您可能想尝试System.loadLibrary(),但请注意您的DLL 必须位于Java 系统属性java.library.path 表示的路径中。 在这种情况下也不要传递完整的文件名,而只传递不带扩展名的文件名。

【讨论】:

  • 它正在寻找 DLL,但我没有正确声明我的函数。我将不得不调查 SWIG。感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多