2

UnsatisfiedLinkErrorとJNIの組み合わせについては、すでに多くのことや質問を見つけましたが、どれも役に立ちませんでした。Javaを使用してウィンドウを非表示にしようとしているので、3つのWinAPI関数が必要です。

私は次のJavaソースを持っています:

package hide.window;
public class HideWindow {

    public native static int hideWindow(char[] windowTitle);

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

    public static void main(String[] args) {
        System.out.println("loadLibrary was successful");
        System.out.println(hideWindow("Session Window - Windows Internet Explorer".toCharArray()));
    }
}

次に、javahによって生成されたhide_window_HideWindow.hがあります。ライブラリパスにjni.hファイルが見つからなかったため、変更しなければならなかったことが1つあります。それをプロジェクトに入れて、次のようにインクルードしました。

#include "jni.h"

これは私のエラーを引き起こす可能性がありますか? ファイル全体:

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

#ifndef _Included_hide_window_HideWindow
#define _Included_hide_window_HideWindow
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     hide_window_HideWindow
 * Method:    hideWindow
 * Signature: ([C)I
 */
JNIEXPORT jint JNICALL Java_hide_window_HideWindow_hideWindow
  (JNIEnv *, jobject, jcharArray);

#ifdef __cplusplus
}
#endif
#endif

DLLにコンパイルしたコードは次のようになります。

#include <windows.h>
#include "hide_window_HideWindow.h"
using namespace std;

JNIEXPORT jint JNICALL Java_hide_window_HideWindow_hideWindow(char windowTitle[20])
{
    HWND windowHandle = FindWindowA(NULL, windowTitle);
    if (windowHandle){
        if (IsWindowVisible(windowHandle)){
            ShowWindow(windowHandle, 0);
            return 0;
        }
        else{
            ShowWindow(windowHandle, 1);
            return 1;
        }
    }
    return -1;
}

eclipseからの呼び出しと、cmdを介した次の呼び出しの間に違いはありません(パスは正しい):

java -Djava.library.path=.. hide.window.HideWindow

結果の出力は次のようになります。

loadLibrary was successful
Exception in thread "main" java.lang.UnsatisfiedLinkError: hide.window.HideWindow.hideWindow([C)I
  at hide.window.HideWindow.hideWindow(Native Method)
  at hide.window.HideWindow.main(HideWindow.java:12)

これは、JavaプログラムがDLLをロードできるが、関数呼び出しで失敗することを示しています。私はEclipseをJavaとして、CodeblocksをC ++ IDEとして使用しており、mingwビルドオプションに次のものをすでに追加しています。

-Wl,--kill-at

この質問があまり愚かではないことを願っています。事前に感謝します、トム

4

1 に答える 1

5

プロトタイプを見てください:

JNIEXPORT jint JNICALL Java_hide_window_HideWindow_hideWindow
    (JNIEnv *, jobject, jcharArray);

とあなたの実装:

JNIEXPORT jint JNICALL Java_hide_window_HideWindow_hideWindow
    (char windowTitle[20])

もちろんUnsatisfiedLinkError、正しい関数を実装しなかったためです。

したがって、次のようなものが必要になります。

JNIEXPORT jint JNICALL Java_hide_window_HideWindow_hideWindow
    (JNIEnv* env, jobject thiz, jcharArray windowTitle)

配列から文字を取り出すには、GetPrimitiveArrayCritialまたはを参照してくださいGetCharArrayRegion

生成されたヘッダーも私には疑わしいように見えます。これは、Javaメソッドを定義したが、生成されたプロトタイプが...静的メソッドstaticの必要性を渡したいためです(静的メソッド呼び出しのインスタンスオブジェクトがないため)。jobjectjclass

JNIEXPORT jint JNICALL Java_hide_window_HideWindow_hideWindow
    (JNIEnv* env, jclass clazz, jcharArray windowTitle)

もう1つのこと:Javaのcharjchar)はunsigned int16、C /C++charが符号付きまたは符号なしint8です。Stringしたがって、 (jstring)を渡して、。を使用してUTF8文字列としてコンテンツを取得する方がよい場合がありますGetStringUTFChars

于 2012-04-27T08:50:05.143 に答える