2

我正在尝试在 Eclipse 中的 java 应用程序中使用 dll,但是每当我尝试调用与该 dll 关联的任何方法时,都会出现运行时异常。

该dll存在于以下地址,我在eclipse中的Run/Debug Settings中传入了该地址:

-Djava.library.path="C:\Program Files\NPortAdminSuite\ipserial\lib\x86;${env_var:PATH}"

代码:

类测试{

  public native int nsio_init();

  public static void main(String[] args) {
          System.loadLibrary("ipserial");
          new Test().nsio_init(); //This part is throwing an exception
  }
}

错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: NPortConnection.nsio_init()I
    at Test.nsio_init(Native Method)
    at Test.main(Test.java:27)

该命令dumpbin /exports "C:\Program Files\NPortAdminSuite\ipserial\lib\x86\IPSerial.dll"还返回我试图从该 dll 调用的方法的名称 在此处输入图像描述

谁能告诉如何解决这个问题?

4

2 回答 2

4

看起来您正试图直接从 java 代码调用 dll 函数。这是不可能的(直接)。您需要编写一个在 java 和本机 dll 之间转换的层。

看看这些资源:


解决该问题的另一种方法是使用JNA,例如查看维基百科文章

于 2012-07-02T05:56:05.233 回答
2

编辑:   另请参阅使用函数而不是底部预处理器宏的优雅答案


如果你想实现JNI,我就是这样做的:

让我们想象一下文件中的以下类example.java

package my.group.mypackage;

public class Example {
  static {
    System.loadLibrary("my-DLL-name");
  }

  public Example() {
    /* ... */
  }

  private native int    function1(int); //declare DLL functions
  private native String function2(int); //using the keyword
  private native void   function3(int); //'native'

  public void dosomething(int value) {
    int result = function1(value);  
    String str = function2(value);  //call your DLL functions
    function3(value);               //as any other java function
  }
}

example.classexample.java(使用javac或您的 EDI 或 maven ...)生成。然后Java_my_group_mypackage_example.h使用. example.class_javah

C/C++ 函数的声明在Java_my_group_mypackage_example.h. 现在我们例如实现这些函数的定义(主体)Java_my_group_mypackage_example.cpp。更喜欢使用 C++(而不是 C)来捕获来自其他 DLL 的异常。

JNIEXPORT jlong JNICALL Java_my_group_mypackage_example_function1
  (JNIEnv *env, jobject object, jlong value)
{
  try 
  {
    /* ... my processing ... */
    return jlong(result);
  }
  CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
  return 0;
}

JNIEXPORT jstring JNICALL Java_my_group_mypackage_example_function2
  (JNIEnv *env, jobject object, jlong value)
{
  try 
  {
    /* ... my processing ... */
    jstring jstr = env->NewStringUTF("my result");
    return  jstr;
  }
  CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
  return 0;
}

JNIEXPORT void JNICALL Java_my_group_mypackage_example_function3
  (JNIEnv *env, jobject object, jlong value)
{
  try 
  {
    /* ... my processing ... */
  }
  CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION
}

C 预处理器宏CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION定义如下。它将 C++ 异常转换为 Java 异常。使用您自己的代码自定义该代码mypackage::Exception并将其放在一个公共标头中(不在 `Java_my_group_mypackage_example.h' 中,因为它可以再次重新生成)。

#define CATCH_CPP_EXCEPTION_AND_THROW_JAVA_EXCEPTION              \
                                                                  \
  catch (const mypackage::Exception& e)                           \
  {                                                               \
    jclass jc = env->FindClass("my/group/mypackage/Exception");   \
    if(jc) env->ThrowNew (jc, e.what());                          \
    /* if null => NoClassDefFoundError already thrown */          \
  }                                                               \
  catch (const std::bad_alloc& e)                                 \
  {                                                               \
    /* OOM exception */                                           \
    jclass jc = env->FindClass("java/lang/OutOfMemoryError");     \
    if(jc) env->ThrowNew (jc, e.what());                          \
  }                                                               \
  catch (const std::ios_base::failure& e)                         \
  {                                                               \
    /* IO exception */                                            \
    jclass jc = env->FindClass("java/io/IOException");            \
    if(jc) env->ThrowNew (jc, e.what());                          \
  }                                                               \
  catch (const std::exception& e)                                 \
  {                                                               \
    /* unknown exception */                                       \
    jclass jc = env->FindClass("java/lang/Error");                \
    if(jc) env->ThrowNew (jc, e.what());                          \
  }                                                               \
  catch (...)                                                     \
  {                                                               \
    /* Oops I missed identifying this exception! */               \
    jclass jc = env->FindClass("java/lang/Error");                \
    if(jc) env->ThrowNew (jc, "unidentified exception");          \
  }

编译Java_my_group_mypackage_example.cpp生成 DLL。PATH在您的 java 运行时目录(通常target)中设置或移动该 DLL。

不要忘记用"my-DLL-name"不带扩​​展名的 DLL 名称替换 java 源代码中的名称(例如myname.dll-> "myname")。

这也适用于 Linux/Unix 共享库 ( *.so) ;-)

于 2013-03-08T09:15:20.253 回答