4

C++ dll を呼び出す必要がある独自のビルド Eclipse プラグインがあります。

私は2つのステップでこれをやろうとしました:1.C++ dllを呼び出すJavaメインプログラムを介して私のEclipseプラグインの外で2.それを私のプラグインに入れようとします(これが問題の場所です)

  1. 外部 Eclipse プラグイン。

メイン Java コード HelloWorld.java。

class HelloWorld {
    //public native void print();  //native method
    public native String print(String msg);  //native method

    static   //static initializer code
    {
        System.loadLibrary("CLibHelloWorld");
    } 

    public static void main(String[] args)
    {
    //HelloWorld hw = new HelloWorld();
        //hw.print();

    String result = new HelloWorld().print("Hello from Java");

    System.out.println("In Java, the returned string is: " + result);
    }
}

コマンドでコンパイル: "C:\Program Files\Java\jdk1.6.0_34\bin\javac" HelloWorld.java

次に、次の方法で C++ dll 用の h-file HelloWorld.h を作成しました。

"C:\Program Files\Java\jdk1.6.0_34\bin\javah" HelloWorld

h ファイルは次のようになります。

#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

C++ dll CLibHelloWorld.cpp :

#include "HelloWorld.h"
#include "jni.h"
#include "stdafx.h"
#include "tchar.h"

#import "..\ManagedVBDLL\bin\Debug\ManagedVBDLL.tlb" raw_interfaces_only
using namespace ManagedVBDLL;

JNIEXPORT jstring JNICALL Java_HelloWorld_print(JNIEnv *env, jobject thisObj, jstring inJNIStr) {
   jboolean blnIsCopy;
   const char *inCStr;
   char outCStr [128] = "string from C++";

   inCStr = env->GetStringUTFChars(inJNIStr, &blnIsCopy);
   if (NULL == inCStr) return NULL;

   printf("In C, the received string is: %s\n", inCStr);
   env->ReleaseStringUTFChars(inJNIStr, inCStr);  

   return env->NewStringUTF(outCStr);
}

dll をビルドする

Javaメインプログラムを実行すると...すべて正常に動作します!

  1. 私のEclipseプラグインにそれを入れてみてください(これが問題の場所です)

C++ dll を呼び出すクラスを作成しました。

package org.eclipse.ui.examples.recipeeditor.support;
import org.eclipse.jface.dialogs.MessageDialog;

public class HelloWorld {
    public native String print(String msg);  //native method

    static   //static initializer code
    {
        try {
            System.loadLibrary("CLibHelloWorld"); //$NON-NLS-1$
        } catch (Exception e) {
            e.printStackTrace();
            MessageDialog.openInformation(null, "HelloWorld", "HelloWorld Catch: " + e.getMessage());
        }
    } 
}

そしてそれを次のように呼び出します:

HelloWorld hw = new HelloWorld();
result = hw.print("Hi from Eclipse");

次に、hw.printでこのエラーが発生します(dllのロードが完了しました):

java.lang.UnsatisfiedLinkError: org.eclipse.ui.examples.recipeeditor.support.HelloWorld.print(Ljava/lang/String;)Ljava/lang/String;

長い話ですが、どうすれば解決できますか?

ありがとう。

4

2 に答える 2

0

System.loadLibrary は、ライブラリが LD_LIBRARY_PATH (Linux) または PATH (Windows) で使用可能な場合にのみ、ライブラリをロードします。また、正しい名前を尊重する必要があります。Windowsではわかりませんが、LinuxであなたがしたようにロードCLibHelloWorldしている場合、DLLはlibCLibHelloWorld.so. System.getNativeMethodName などがあると思いますので、それを見つけることができます。

とにかく、多くの環境設定に依存しているため、これは DLL をロードする私の好みの方法ではありません。System.load (dll_full_path)代わりに、 DLL をロードするために使用できます。同じ効果がありますが、より細かく制御できます。

ただし、このメソッドを使用して DLL を正常にロードし、ネイティブ メソッドを呼び出そうとすると上記のエラーが引き続き発生する場合は、DLL の依存関係を調べてください。最初に依存関係をロードし、次に呼び出したいライブラリをロードする必要があります。

たとえば、dll3 に依存する dll2 に依存する dll1 をロードする場合は、次のようにします。

System.load(dll3_path);
System.load(dll2_path);
System.load(dll1_path);
于 2012-11-29T04:50:15.290 に答える