Mark Jeronimus
Mark Jeronimus

Reputation: 9543

JNA runtime dependent library not found

I'm trying to use a pre-existing stdcall DLL in JNA and one of the functions keeps complaining that a runtime-dependent dll can not be found. In an equivalent JNI version, I don't get this complaint and it works as expected.

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

When I call function USBEnumerateDevices I get the return value 0xFFF5, which according to the manual means "MPDeviceDriver.dll not found"

The file MPDeviceDriver.dll is in the same path as MP300Com.dll, and both are as well in c:\windows\sysWOW64

I also tried adding System.loadLibrary("MPDeviceDriver"); before and after the other load, without success. I can verify that it gets loaded — by JNA — because I can't delete the MPDeviceDriver.dll in my project folder (it's locked).

As said before, when the JNI version calls this function, I get return value 0x0 (ok) and the devices are enumerated correctly. Excerpt from the JNI code:

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

With dependency walker, I don't see any obviously missing dependencies, and moreover, MPDeviceDriver.dll is not listed as a dependency. I guess it gets loaded manually, by the code itself.

I'm positive the way of calling USBEnumerateDevices in JNA is correct, because when I replace MP300Com.dll with a very old version (one that doesn't depend on MPDeviceDriver.dll) the device gets enumerated correctly. (the pSerialList contains my the device string)

Link to the function definition in the manual

Upvotes: 1

Views: 347

Answers (1)

Mark Jeronimus
Mark Jeronimus

Reputation: 9543

After a colleague tried some simplified tests it suddenly worked, and after I tried to translate the exact order of calls into the framework, it again didn't work. It turns out this specific DLL is thread-sensitive, and in a most twisted way:

  • If the thread loading the DLL and the thread using the DLL for the first time are the same, the DLL works in all threads.
  • If the thread loading the DLL and the thread using the DLL for the first time are different, none of those threads can use the DLL, but another thread spawned from another ThreadGroup could use the DLL.

Upvotes: 1

Related Questions