JNI问题:在Java中调用使用第三方Dll的Dll

JNI问题:在Java中调用使用第三方Dll的Dll,java,dll,java-native-interface,Java,Dll,Java Native Interface,我想使用epanet.dll,所以为了调用它,我必须创建我的桥dll 我创建了Java类 public class Epanet { //Native method declaration native int ENopen(String fileInput, String fileOutput, String optBinFileOut); native int ENsaveinpfile(String file); native int ENclose();

我想使用epanet.dll,所以为了调用它,我必须创建我的桥dll

我创建了Java类

public class Epanet {

   //Native method declaration
   native int  ENopen(String fileInput, String fileOutput, String optBinFileOut);
   native int  ENsaveinpfile(String file);
   native int  ENclose();
   native int  ENsolveH();
   native int  ENsaveH();
   native int  ENopenH();
   //native int  ENrunQ(long *);

   //Load the library
   static {
     System.loadLibrary("epanet2");
   }
}
然后javah创建了de.h文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class Epanet */

#ifndef _Included_Epanet
#define _Included_Epanet
#ifdef __cplusplus
extern "C" {
   #endif

   JNIEXPORT jint JNICALL Java_Epanet_ENopen (JNIEnv *, jobject, jstring, jstring, jstring);

   JNIEXPORT jint JNICALL Java_Epanet_ENsaveinpfile (JNIEnv *, jobject, jstring);

   JNIEXPORT jint JNICALL Java_Epanet_ENclose (JNIEnv *, jobject);

   JNIEXPORT jint JNICALL Java_Epanet_ENsolveH (JNIEnv *, jobject);

   .....
   .....

   #ifdef __cplusplus
}
#endif
#endif
然后我创建了一个.c文件,该文件应该调用epanet2 dll

#include "jni.h"
#include <stdio.h>
#include "myDll.h"
#include "epanet2.h"

JNIEXPORT jint JNICALL Java_Epanet_ENopen
  (JNIEnv *env, jobject obj, jstring fichIn, jstring fichOut, jstring fichBin){

       const char *CStringFichIn = (*env)->GetStringUTFChars(env,fichIn,NULL);
       const char *CStringFichOut =  (*env)->GetStringUTFChars(env,fichOut,NULL);
       const char *CStringFichBin = (*env)->GetStringUTFChars(env,fichBin,NULL);
       int result;

       result =  ENepanet (CStringFichIn, CStringFichOut, CStringFichBin, NULL);

       (*env)->ReleaseStringUTFChars(env, fichIn, CStringFichIn);
       (*env)->ReleaseStringUTFChars(env, fichOut, CStringFichOut);
       (*env)->ReleaseStringUTFChars(env, fichBin, CStringFichBin);

       return result;
}

JNIEXPORT jint JNICALL Java_Epanet_ENsaveinpfile
  (JNIEnv *env, jobject object, jstring fichOut){

       const char *CStringFichOut;
       int result;

       CStringFichOut = (*env)->GetStringUTFChars(env,fichOut,NULL);

       result =  ENsaveinpfile (CStringFichOut);
       return result;
}

JNIEXPORT jint JNICALL Java_Epanet_ENclose
  (JNIEnv *env, jobject object){

       int result;
       result =  ENclose ();
       return result;
}

JNIEXPORT jint JNICALL Java_Epanet_ENsolveH
  (JNIEnv *env, jobject object){

       int result;    
       result =  ENsolveH ();
       return result;
}

JNIEXPORT jint JNICALL Java_Epanet_ENsaveH
  (JNIEnv *env, jobject object){
       int result;
       result =  ENsaveH ();
       return result;
}

JNIEXPORT jint JNICALL Java_Epanet_ENopenH
  (JNIEnv *env, jobject obj){
       int result;
       result =  ENopenH ();
       return result;
}
我得到这个错误:

    started
 Exception in thread "main" java.lang.UnsatisfiedLinkError: NewClass.epanet(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String)V
            at NewClass.epanet(Native Method)
            at NewClass.main(NewClass.java:18) Java Result: 1
如果我删除了这些库,我会收到错误,说它找不到这些库,所以在某个地方出现了问题。我必须说,一个朋友给了我他的dll,对他有效,但对我无效。我也犯了同样的错误

猜猜看? 另一个问题是如何调用本机方法//native int ENrunQ(long*)

这就是你给我的建议(主要是第二条评论):

我的Epanet类加载我的dll,而不是Epanet dll(第三方dll)

我的测试类不应该加载它。实际上,它不应该加载任何内容,因为Epanet类会加载

public class NewClass {

     public static void main(String[] args) {

         System.out.println("started");
         new Epanet().ENopen("C:\\Red2.inp", "C:\\salida.txt", "");
         System.out.println("finished");
     }
}
那么我的包装器dll应该如下所示:

#include "jni.h"
#include <stdio.h>
#include "myDll.h"
#include "epanet2.h"

JNIEXPORT jint JNICALL Java_Epanet_ENopen
  (JNIEnv *env, jobject obj, jstring fichIn, jstring fichOut, jstring fichBin){

       const char *CStringFichIn = (*env)->GetStringUTFChars(env,fichIn,NULL);
       const char *CStringFichOut =  (*env)->GetStringUTFChars(env,fichOut,NULL);
       const char *CStringFichBin = (*env)->GetStringUTFChars(env,fichBin,NULL);
       int result;

       result =  ENopen (CStringFichIn, CStringFichOut, CStringFichBin);

       (*env)->ReleaseStringUTFChars(env, fichIn, CStringFichIn);
       (*env)->ReleaseStringUTFChars(env, fichOut, CStringFichOut);
       (*env)->ReleaseStringUTFChars(env, fichBin, CStringFichBin);

       return result;
}
#include "jni.h"
#include <stdio.h>
#include <windows.h>
#include "myDll.h"
#include "epanet2.h"

typedef int (* FPTR)(char *, char *, char*);

JNIEXPORT jint JNICALL Java_Epanet_ENopen
  (JNIEnv *env, jobject obj, jstring fichIn, jstring fichOut, jstring fichBin){

        HMODULE dllHandle = LoadLibrary("epanet2.dll");  // cargar librería 

        const char *CStringFichIn = (char *)(*env)->GetStringUTFChars(env,fichIn,NULL);
        const char *CStringFichOut = (char *) (*env)->GetStringUTFChars(env,fichOut,NULL);
        const char *CStringFichBin = (char *)(*env)->GetStringUTFChars(env,fichBin,NULL);
        int result;

        FPTR ENopen = (FPTR) GetProcAddress(dllHandle, "ENopen");

        result =  ENopen (CStringFichIn, CStringFichOut, CStringFichBin );

       (*env)->ReleaseStringUTFChars(env, fichIn, CStringFichIn);
       (*env)->ReleaseStringUTFChars(env, fichOut, CStringFichOut);
       (*env)->ReleaseStringUTFChars(env, fichBin, CStringFichBin);


        FreeLibrary(dllHandle);    // descargar librería
        return result;
}
#包括“jni.h”
#包括
#包括“myDll.h”
#包括“epanet2.h”
JNIEXPORT jint JNICALL Java_Epanet_ePaen
(JNIEnv*env、jobject obj、jstring fichIn、jstring fichOut、jstring fichBin){
const char*CStringFichIn=(*env)->GetStringUTFChars(env,fichIn,NULL);
const char*CStringFichOut=(*env)->GetStringUTFChars(env,fichOut,NULL);
const char*CStringFichBin=(*env)->GetStringUTFChars(env,fichBin,NULL);
int结果;
结果=内啡肽(CStringFichIn,CStringFichOut,CStringFichBin);
(*env)->释放StringUTFChars(env、fichIn、CStringFichIn);
(*env)->释放StringUTFChars(env、fichOut、CStringFichOut);
(*env)->释放StringUTFChars(env、fichBin、CStringFichBin);
返回结果;
}
或者更像这样:

#include "jni.h"
#include <stdio.h>
#include "myDll.h"
#include "epanet2.h"

JNIEXPORT jint JNICALL Java_Epanet_ENopen
  (JNIEnv *env, jobject obj, jstring fichIn, jstring fichOut, jstring fichBin){

       const char *CStringFichIn = (*env)->GetStringUTFChars(env,fichIn,NULL);
       const char *CStringFichOut =  (*env)->GetStringUTFChars(env,fichOut,NULL);
       const char *CStringFichBin = (*env)->GetStringUTFChars(env,fichBin,NULL);
       int result;

       result =  ENopen (CStringFichIn, CStringFichOut, CStringFichBin);

       (*env)->ReleaseStringUTFChars(env, fichIn, CStringFichIn);
       (*env)->ReleaseStringUTFChars(env, fichOut, CStringFichOut);
       (*env)->ReleaseStringUTFChars(env, fichBin, CStringFichBin);

       return result;
}
#include "jni.h"
#include <stdio.h>
#include <windows.h>
#include "myDll.h"
#include "epanet2.h"

typedef int (* FPTR)(char *, char *, char*);

JNIEXPORT jint JNICALL Java_Epanet_ENopen
  (JNIEnv *env, jobject obj, jstring fichIn, jstring fichOut, jstring fichBin){

        HMODULE dllHandle = LoadLibrary("epanet2.dll");  // cargar librería 

        const char *CStringFichIn = (char *)(*env)->GetStringUTFChars(env,fichIn,NULL);
        const char *CStringFichOut = (char *) (*env)->GetStringUTFChars(env,fichOut,NULL);
        const char *CStringFichBin = (char *)(*env)->GetStringUTFChars(env,fichBin,NULL);
        int result;

        FPTR ENopen = (FPTR) GetProcAddress(dllHandle, "ENopen");

        result =  ENopen (CStringFichIn, CStringFichOut, CStringFichBin );

       (*env)->ReleaseStringUTFChars(env, fichIn, CStringFichIn);
       (*env)->ReleaseStringUTFChars(env, fichOut, CStringFichOut);
       (*env)->ReleaseStringUTFChars(env, fichBin, CStringFichBin);


        FreeLibrary(dllHandle);    // descargar librería
        return result;
}
#包括“jni.h”
#包括
#包括
#包括“myDll.h”
#包括“epanet2.h”
typedef int(*FPTR)(字符*,字符*,字符*);
JNIEXPORT jint JNICALL Java_Epanet_ePaen
(JNIEnv*env、jobject obj、jstring fichIn、jstring fichOut、jstring fichBin){
HMODULE dllHandle=LoadLibrary(“epanat2.dll”);//卡加·利布雷里亚
const char*CStringFichIn=(char*)(*env)->GetStringUTFChars(env,fichIn,NULL);
const char*CStringFichOut=(char*)(*env)->GetStringUTFChars(env,fichOut,NULL);
const char*CStringFichBin=(char*)(*env)->GetStringUTFChars(env,fichBin,NULL);
int结果;
FPTR ENopen=(FPTR)GetProcAddress(dllHandle,“ENopen”);
结果=内啡肽(CStringFichIn,CStringFichOut,CStringFichBin);
(*env)->释放StringUTFChars(env、fichIn、CStringFichIn);
(*env)->释放StringUTFChars(env、fichOut、CStringFichOut);
(*env)->释放StringUTFChars(env、fichBin、CStringFichBin);
自由图书馆(dllHandle);//迪斯卡尔·利布雷里亚
返回结果;
}
另外,您知道如何调用此函数吗

本地英伦(长*)

我不知道如何在mydll中获得long*,因为string->jstring或int->jint但是long*->?还是int*->

我的两分钱:

包装器DLL包含
Epanet
类中本机方法的实现,而不是测试代码中调用的本机方法的实现(请注意stacktrace中的类名)。我认为您应该使用
new Epanet().enpoen(“C:\\Red2.inp”、“C:\\salaida.txt”、“enpoen”)取而代之


另外,
Epanet
的静态初始值设定项应该加载DLL,而不是包装库(如果包装器构建正确,操作系统将负责加载)。

您已经为两个Java类和一个本机实现提供了源代码。这确实让我们更难理解。摆脱新阶级

您希望您的Epanet java类在
System.loadLibrary()
调用中加载其本机包装,然后您的包装dll将自动加载Epanet.dll

就向本机代码中传递长*而言,您不能。创建java-c包装类的技巧在于,您不能直接调用原始方法!您可以传入一个简单的long,但是对long所做的任何更改都将丢失。因此,您可以将可变java对象传递到包装器调用并对其进行更改,或者更简单地让本机方法更改Epanet类的某些状态。

我建议尝试查看是否有您可能需要的其他DLL(例如,您可能缺少Microsoft C运行时)。

我不知道如何在mydll中获得long*,因为string->jstring或int->jint但是long*->???或int*->???? 长*->jlongArray(和int*->jintArray)

例如: 在java本机方法声明中接受长[],在jni中,您将在该参数位置看到jlongArray。使用GetDoubleArrayElements()将jlongArray转换为jlong*(参见文档链接),并且jlong是64位(),您可以使用它。
boolean、int、java对象也一样(请参阅文档了解变化)


在你第一次更新之前
线程“main”java.lang.UnsatisfiedLinkError中出现异常:NewClass.epanet(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String)V
我猜您在编译和/或管理方面犯了错误

public class NewClass {
     private native void ENopen(String f1, String f2, String f3);
原因:错误应该是

java.lang.UnsatifiedLinkError:NewClass.ENopen(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String)V


它们在源代码中不是方法名“NewClass.epanet”(即使在更新之后)。

您已检查bin文件夹中是否存在错误的dll?为什么有两个
loadLibrary(…)
调用?你只有一个界面!我不知道如何检查是否有错误的dll。一切正常。此外,我使用javah生成de.h的类中有一个loadlibrary。另一个是加载我创建的库来测试它。糟糕的缩进:(不能帮助任何人理解代码。我已经更改了对new Epanet()的调用。enpoen(…),现在我得到了一个错误。在处理这个问题一周后,这很好:d第二条评论