簡體   English   中英

調用本機方法時返回java.lang.UnsatisfiedLinkError

[英]java.lang.UnsatisfiedLinkError returned when calling native method

我正在嘗試為第三方DLL制作Java包裝器。 我創建了自己的DLL,充當JNI和第三方DLL之間的中間人。 在java中我加載此DLL很好,但返回錯誤java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Z . 可能導致此錯誤的原因是什么?我可以正確調試它?

Main.java:

package sixense_test;

import sixense.ControllerData;
import sixense.Sixense;

public class Main {

    public static ControllerData[] controllers = new ControllerData[4];
    public static boolean quit;

    public static void main(String[] args) {
        if(Sixense.init()) {
            Sixense.setActiveBase(0);
            Sixense.getAllNewestData(controllers);
            System.out.println("X: " + controllers[0].pos[0] + "Y: " + controllers[0].pos[1] + "Z: " + controllers[0].pos[2]);
        }
    }
}

Sixense.java:

package sixense;

public class Sixense {
    public static native boolean init();
    public static native boolean exit();
    public static native int getMaxBases();
    public static native boolean setActiveBase( int base_num );
    public static native boolean isBaseConnected( int base_num );
    public static native int getMaxControllers();
    public static native int getNumActiveControllers();
    public static native boolean isControllerEnabled( int controller_id );
    public static native boolean getAllNewestData( ControllerData[] all_data );
    public static native boolean getAllData( int index_back, ControllerData[] all_data );
    public static native boolean getNewestData( int controller_id, ControllerData data );
    public static native boolean getData( int controller_id, int index_back, ControllerData all_data );
    public static native int getHistorySize();
    public static native boolean setFilterEnabled( boolean on_or_off );
    public static native boolean getFilterEnabled();
    public static native boolean setFilterParams( float near_range, float near_val, float far_range, float far_val );
    public static native boolean getFilterParams( float[] params );
    public static native boolean triggerVibration( int controller_id, int duration, int pattern_id );
    public static native boolean autoEnableHemisphereTracking( int controller_id );
    public static native boolean setHighPriorityBinding( boolean on_or_off );
    public static native boolean getHighPriorityBinding();
    public static native boolean setBaseColor( int red, int green, int blue );
    public static native boolean getColorBase( int[] colors );
    static {
        System.loadLibrary("Sixense_Java");
    }
}

摘自sixense_Sixense.cpp:

#include <jni.h>
#include <sixense.h>
#include "sixense_Sixense.h"

JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init(JNIEnv *env, jclass obj) {
    int i;
    i = sixenseInit();
    return (i == -1) ? JNI_FALSE : JNI_TRUE;
}

摘自sixense_Sixense.h:

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

#ifndef _Included_sixense_Sixense
#define _Included_sixense_Sixense
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     sixense_Sixense
 * Method:    init
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init
  (JNIEnv *, jclass);

dumpbin的輸出:

File Type: DLL

  Section contains the following exports for Sixense_Java.dll

    00000000 characteristics
    4FFBC481 time date stamp Tue Jul 10 01:58:25 2012
        0.00 version
           1 ordinal base
          23 number of functions
          23 number of names

    ordinal hint RVA      name

          1    0 00001D10 Java_sixense_Sixense_autoEnableHemisphereTracking@12
          2    1 000011A0 Java_sixense_Sixense_exit@8
          3    2 00001A40 Java_sixense_Sixense_getAllData@16
          4    3 000019A0 Java_sixense_Sixense_getAllNewestData@12
          5    4 00001DC0 Java_sixense_Sixense_getColorBase@12
          6    5 00001B30 Java_sixense_Sixense_getData@20
          7    6 00001BD0 Java_sixense_Sixense_getFilterEnabled@8
          8    7 00001C40 Java_sixense_Sixense_getFilterParams@12
          9    8 00001D60 Java_sixense_Sixense_getHighPriorityBinding@8
         10    9 00001B90 Java_sixense_Sixense_getHistorySize@8
         11    A 000011C0 Java_sixense_Sixense_getMaxBases@8
         12    B 00001210 Java_sixense_Sixense_getMaxControllers@8
         13    C 00001AE0 Java_sixense_Sixense_getNewestData@16
         14    D 00001220 Java_sixense_Sixense_getNumActiveControllers@8
         15    E 00001180 Java_sixense_Sixense_init@8
         16    F 000011F0 Java_sixense_Sixense_isBaseConnected@12
         17   10 00001230 Java_sixense_Sixense_isControllerEnabled@12
         18   11 000011D0 Java_sixense_Sixense_setActiveBase@12
         19   12 00001D90 Java_sixense_Sixense_setBaseColor@20
         20   13 00001BA0 Java_sixense_Sixense_setFilterEnabled@12
         21   14 00001C00 Java_sixense_Sixense_setFilterParams@24
         22   15 00001D30 Java_sixense_Sixense_setHighPriorityBinding@12
         23   16 00001CE0 Java_sixense_Sixense_triggerVibration@20

  Summary

        1000 .bss
        1000 .data
        1000 .edata
        1000 .idata
        1000 .rdata
        1000 .reloc
        2000 .text

在Java中調用本機函數時,運行時會嘗試使用:

  • stdcall樣式的裝飾函數: _functionName@n ,其中n是參數列表中的字節數,
  • 和一個cdecl風格的未修飾函數: functionName

在使用MinGW進行編譯時,您將得到這兩者的混合:MinGW將追加@n ,但不會添加下划線: functionName@n

解決這個問題的方法是告訴ld不要添加后綴,使用--kill-at開關(或--kill-at -Wl,--kill-at如果通過GCC調用它-Wl,--kill-at則為-Wl,--kill-at )。

我找到了答案! 似乎在Windows中使用JNI時,它會查找以_Java_開頭的函數,而在其他所有平台中查找Java_ 為什么會出現這種情況,而不是寫在我不知道的文檔中,但它會使一切工作完美!

java.lang.UnsatisfiedLinkError: no Sixense_Java in java.library.path

看起來Java無法找到庫,你把它放在了正確的位置嗎?

您可能需要更改java.library.path ,看看這個

如果要打印它的內容,請使用:

System.out.println( System.getProperties().getProperty("java.library.path"));

這可能會打印很多,您可能想要split(";")並自行打印每個條目。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM