views:

207

answers:

1

I've successfully compiled my library on Linux and Mac and used it with Java Native Access. Unfortunately nothing I do seems to work with Visual Studio's compiler and Java Native Access.

I'm going back to the basics and trying to create a super simple dll in Visual Studio that Java Native Access will work with, any help would be appreciated.

Here's GimmeFiveDll.c:

__declspec(dllexport) int gimmeFive()
{
    return 5;
}

Here's SystemLibrary.java:

import com.sun.jna.Native;


public class SystemLibrary {

public static final SystemLibrary instance = new SystemLibrary();

    static {
        Native.register("GimmeFiveDll");
    }

    public native int gimmeFive();
}

I have already tried switching the call interface to stdcall in Visual Studio. I did not make any other changes from the new project wizard's empty project dll win32 console defaults. In the example above the resulting dll doesn't even export the function correctly according to dumpbin.exe /exports. My real project does export them correctly but either way I always get the same JNA exception:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'GimmeFiveDll': The specified module could not be found.

(Yes, I put the GimmeFiveDll.dll in System32. Yes I am able to use JNA to access other dlls in System32 that come with Windows).

Anyone willing to help me round out this minimalist example of a dll created by Visual Studio that JNA likes?

Many many thanks.

+1  A: 

After two days of banging my head against a wall I figured it out. The problem was that C:\Windows\System32 is NOT a directory System.loadLibrary() (which Native.register() uses) can load a dll from on a 64 bit machine! So instead JNA was apparently attempting to copy the library to a temporary location and load it, but that failed. The "specified module could not be found" message wasn't terribly helpful and set me down the wrong track :-\

Anyway to answer my own question here is an example of a dll that can be built with MSVC that Java (and JNA) can use (just put it in the right directory for your system!):

GimmeFiveDll.c:

#ifdef __cplusplus
#error no C++, to keep this example simple
#endif

__declspec(dllexport) int gimmeFive()
{
    return 5;
}

DllTest.java:

import com.sun.jna.Native;

public class DllTest {

    static {
        Native.register("GimmeFiveDll");
    }

    public static native int gimmeFive();

    public static void main(String[] args) {
        System.out.println("I got: " + DllTest.gimmeFive());
    }
}

If all goes well Java will print "I got: 5".

Note that I did not find it necessary to change the compiler settings to use stdcall or to declare __stdcall in the function signature. In fact no compiler changes were needed from the normal empty dll project the wizard creates.

Yuvi Masory
What you're doing is slightly abusive, instead of `new DllTest()` you should make your function definition `public static native int gimmeFive();` and access it as `DllTest.gimmeFive();` (the rationale here is that the DLL is loaded as part of the static initializer)
Mark E
I like your suggestion and changed the code accordingly. Thanks!
Yuvi Masory
I found this out the hard way too (the wrong directory part)
brian_d