2010-11-21 14 views
1

epanet.dllを使用して呼び出すには、ブリッジDLLを作成する必要があります。私はepanet2 DLLを呼び出す必要があります.cファイルを作成した後JNIの問題:サードパーティのDLLを使用するDLLをJavaで呼び出す

/* 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 

.hファイルデ作成javahは

は私が

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"); 
    } 
} 

そして、Javaクラスを作成し

#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; 
} 

そして、コンパイルします。 Visual C++で自分のdllが作成されます。私は両方のdllをsystem32にコピーしました。それから私は私のDLLを使用しようとします。

public class NewClass { 
    private native void ENopen(String f1, String f2, String f3); 

    public static void main(String[] args) { 

     System.out.println("started"); 
     new NewClass().ENopen("C:\\Red2.inp", "C:\\salaida.txt", ""); 
     System.out.println("finished"); 
    } 

    static { 
     System.loadLibrary("myDll"); 
    } 
} 

私はこのエラーを取得する:

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を私にくれたと言わなければならないが、それは私にとってはうまくいかない。私は同じエラーが発生します。

もう1つの質問は、このネイティブメソッド// native int ENrunQ(long *)を呼び出す方法です。 ?

は、これはあなたが(主に第2のコメントのために)私を示唆するものである:

マイEpanetクラスはepanetのDLL(サードパーティのものを)私のDLLをロードしません。

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("myDll"); 
    } 
} 

私のテストクラスはロードしないでください。実際には、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; 
} 

また、あなたはこの関数を呼び出す方法を知っているのですか? > JSTRINGまたはINT - - > JINTが、長い* - >

native int ENrunQ(long *);

ため、私は、文字列MYDLLに長い*得るのですか分かりませんか?またはint * - >?

+0

binフォルダに不完全なdllがないことを確認しましたか? – dacwe

+0

なぜ2つの 'loadLibrary(..)'呼び出しがありますか?インターフェイスは1つだけです! – dacwe

+0

欠陥のあるDLLがあるかどうかを確認する方法がわかりません。すべてうまく動作します。 – Alberto

答えて

0

私の2セント:

ラッパーDLLは、(スタックトレース内のクラス名を注意してください)あなたのEpanetクラスではなく、あなたがテストコードで呼び出しているネイティブメソッドのネイティブメソッドの実装が含まれています。代わりにnew Epanet().ENopen("C:\\Red2.inp", "C:\\salaida.txt", "");を使用してください。

また、Epanetの静的イニシャライザは、ラップされたライブラリではなく、DLLをロードする必要があります(ラッパーが正しく構築されていれば、OSはそれを処理します)。

+0

私は呼び出しを変更しました新しいEpanet()へENopen(......)今、私はエラーが発生します。これは1週間後にうまくいっています:D – Alberto

+0

2番目のコメントは私がそれを修正する方法を知らないと言います。 – Alberto

0

2つのJavaクラスと1つのネイティブ実装のソースを提供しました。それは私たちが理解することをより困難にします。NewClassを取り除く。

Epanet JavaクラスにSystem.loadLibrary()呼び出しでネイティブラッパーをロードし、ラッパーdllが自動的にepanet.dllをロードするようにします。

長い*をネイティブコードに渡すという点では、できません。 Java-Cラッパークラスを作成するスキルは、元のメソッドを直接呼び出すことはできません!あなたは単純な長さで渡すことができますが、長い変更は失われます。したがって、ラッパー呼び出しに変更可能なJavaオブジェクトを渡して変更するか、または単純にネイティブメソッドでEpanetクラスの状態を変更することができます。

+0

私が投稿した新しいソリューションを確認してください。 – Alberto

+0

2番目のコメントに関して、私はあなたを理解していると思います。私のJavaクラスは、jlong​​として長くdllに渡されます。次に、mydllに長いvarを作成し、jlong​​をコピーし、&longというネイティブメソッドを呼び出します。あなたの言うように、私のdllが返ってくると、長いvarの変更は失われます。 – Alberto

0

Dependency Walkerには、必要に応じて他のDLLがあるかどうかを確認することをお勧めします(たとえば、Microsoft Cランタイムが不足している可能性があります)。

+0

Tここにどこかで問題があった。私は最初からすべてを再構築しています。依存関係も調べて、私のdllはepanet.dllに依存しています。 – Alberto

0

http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

I don't know how do get long* in mydll because string -> jstring or int -> jint but long* -> ??? or int* -> ???? that long* -> jlongArray (and int* ->jintArray)

例: 長い[] Javaネイティブメソッドの宣言では、JNIであなたがその引数の位置にjlong​​Arrayが表示されます受け入れます。 GetDoubleArrayElements()(docのリンクを参照)を使用してjlong​​Arrayをjlong​​ *に変換し、jlong​​が64ビット(http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html)であれば使用できます。ブール、int型、Javaオブジェクト(変動についてのドキュメントを参照)と同じ
....


前に、あなたの最初の更新 Exception in thread "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); 

理由:NewClass:エラーが

ます。java.lang.UnsatisfiedLinkErrorされている必要があります。 ENopen(Ljava/LANG /文字列; Ljava/LANG /文字列; Ljava/LANG /文字列)V

(でも、更新後の)あなたのソース内のメソッド名 "NewClass.epanet" 自分ではありません。

関連する問題