JNA and DLLs are completely new territory for me... I have a custom DLL that has a function with this declaration:
int myfunc (const char*);
The dll compiles fine under MinGW with the following command:
>gcc -shared -omydll.dll mydll.c -lgdi32
However, loading it with JNA fails because it can't find the function within the DLL.
public interface mydll extends StdCallLibrary {
mydll INSTANCE = (mydll)Native.loadLibrary("mydll", mydll.class);
int myfunc (String arg);
}
I did some research and it seems that this particular error has something to do with the calling procedure of the DLL functions. I've seen the __stdcall
and the __cdecl
procedures. I also saw that many DLL functions put __declspec(dllexport)
in front of their function declarations/implementations (i have no idea what this means or what it does). So, since JNA seems to like the __stdcall
procedure better, now my function looks like this:
__declspec(dllexport) int __stdcall myfunc (const char*);
Which looks super-complicated, but does no better than anything else i've tried. Using a HashMap to add the underscore prefix and the @4 suffix didn't work either:
mydll INSTANCE = (mydll)Native.loadLibrary("mydll", mydll.class, new HashMap () {{
add("myfunc", "_myfunc@4");
}});
The JNA documentation has been absolutely no help. I honestly have no idea what i'm doing anymore.
Turns out that i was building my DLL just fine, and JNA was finding my DLL just fine as well; i made an error in determining how the compiler mangled my symbols. Functions i named like myfunc
were exported as myfunc@8
or myfunc@32
depending on how many bytes they took as arguments. Here's the code i used in my JNA project:
import java.util.*;
import com.sun.jna.*;
import com.sun.jna.win32.*;
//
public class Test
{
public interface mydll extends StdCallLibrary
{
mydll INSTANCE = Native.loadLibrary("mydll", mydll.class, new HashMap {{
put("myfunc", "myfunc@8");
//Other functions
}});
public int myfunc (long arg);
//Other functions
}
//
public static void main (String[] args)
{
System.out.println
(mydll.INSTANCE.myfunc((long)0x23A3920F)); //Or whatever
return 0;
}
}
My c code:
#include <windows.h>
#include <stdio.h>
__declspec(dllexport) int __stdcall myfunc (__int64);
/* Other functions */
__declspec(dllexport) int __stdcall myfunc (__int64 arg)
{
/* Whatever */
return return_value;
}
GCC was happy with just the -shared
switch and linking against the proper libraries, like in my original question. I highly recommend downloading this tool so you can find out exactly what your function names are.