2015-04-17 109 views
1

我想在JNA中使用預先存在的stdcall DLL,並且其中一個函數一直在抱怨找不到與運行時相關的DLL。在一個等價的JNI版本中,我沒有得到這個投訴,它按預期工作。未找到JNA運行時依賴庫

System.loadLibrary("MP300Com"); 

Map<String, Object> functionMapper = new HashMap<>(); 
functionMapper.put(
     Library.OPTION_FUNCTION_MAPPER, 
     new StdCallFunctionMapper()); 

library = (Mp300Library)Native.loadLibrary(
     "MP300Com", 
     Mp300Library.class, 
     functionMapper); 

 

public interface Mp300Library extends StdCallLibrary { 
    int USBEnumerateDevices(IntByReference pNbMP300, Pointer ppSerialList); 
} 

 

public static String[] USBEnumerateDevices() throws Mp300Exception { 
    Memory pSerialList = new Memory(512); 
    IntByReference pNbMP300 = new IntByReference(); 
    Pointer ppSerialList = new Memory(Pointer.SIZE); 
    ppSerialList.setPointer(0, pSerialList); 
    int status = library.USBEnumerateDevices(pNbMP300, ppSerialList); 
    System.out.println(status); // 65525 = 0xfff5 
    return null; 
} 

當我打電話功能USBEnumerateDevices我得到的返回值0xFFF5,根據手冊,這意味着 「MPDeviceDriver.dll找不到」

MPDeviceDriver.dll文件是我的與MP300Com.dll相同的路徑,並且都在c:\ windows \ sysWOW64中也是如此。

我也嘗試在其他加載之前和之後添加System.loadLibrary("MPDeviceDriver");,但沒有成功。我可以驗證它是否被加載 - 通過JNA - 因爲我無法刪除我的項目文件夾中的MPDeviceDriver.dll(它已被鎖定)。

如前所述,當JNI版本調用此函數時,我得到返回值0x0(ok),並且設備正確枚舉。從JNI代碼摘錄:

int nbMp = 0; 
char devlist[512]; 
char *pList = devlist; 
WORD ret = USBEnumerateDevices(&nbMp, &pList); 

隨着Dependency Walker中,我沒有看到任何明顯缺少的依賴關係,而且,MPDeviceDriver.dll沒有被列爲依賴關係。我猜它是由代碼本身手動加載的。

我很積極在JNA中調用USBEnumerateDevices的方式是正確的,因爲當我用一個非常舊的版本(不依賴於MPDeviceDriver.dll的版本)替換MP300Com.dll時,設備會正確枚舉。 (該pSerialList包含我的設備字符串)

Link to the function definition in the manual

回答

1

後同事嘗試了一些簡單的測試中,它突然的工作,之後我試圖調用的確切順序翻譯成框架,它再次沒有工作。事實證明,這種特定的DLL是線程敏感,並且在最扭曲的方式:

  • 如果線程加載使用DLL DLL和線程首次是相同的,該DLL工程全部個主題。
  • 如果線程首次使用DLL加載DLL和線程是不同,那些線程都不能使用該DLL,但是從另一個ThreadGroup派生的另一個線程可以使用該DLL。