[newbie] UnsatisfiedLinkError with a simple function

227 views
Skip to first unread message

Arnaud Bailly

unread,
Nov 8, 2012, 11:27:28 AM11/8/12
to jna-...@googlegroups.com
Hello,
I am trying to wrap a set of native (C) libraries using JNA and am running into issues I do not understand.

I converted the following C header:

extern _ADLL_DECL_SPEC void                RDBMS_Init             (void);
extern _ADLL_DECL_SPEC void                RDBMS_Shut             (void);
extern _ADLL_DECL_SPEC RDBMS_MXFUNCTION   *RDBMS_pFctGet          (void);

using jnaerator to the following java code

public interface RdbmsStdLibrary extends Library {

    String JNA_LIBRARY_NAME = "rdbms_std";
    NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(RdbmsStdLibrary.JNA_LIBRARY_NAME);
    RdbmsStdLibrary INSTANCE = (RdbmsStdLibrary) Native.loadLibrary(RdbmsStdLibrary.JNA_LIBRARY_NAME, RdbmsStdLibrary.class);

    void RDBMS_Init();

    void RDBMS_Shut();

    RdbmsStdLibrary.RDBMS_MXFUNCTION RDBMS_pFctGet();

    public static class RDBMS_MXFUNCTION extends PointerType {
        public RDBMS_MXFUNCTION() {
            super();
        }

        public RDBMS_MXFUNCTION(Pointer address) {
            super(address);
        }
    }
}

Then I wrote a simple unit test to try my stuff

    private static final File BASEDIR = new File(System.getProperty("basedir", ".")).getAbsoluteFile();

     @BeforeClass
    public static void setUp() throws Exception {
        System.setProperty("jna.library.path",new File(BASEDIR,"src/test/resources/rdbms").getAbsolutePath());    
    }

    @Test
    public void invokeNativeMethodWhenCallingFunctionOnInstance() throws Exception {
        RdbmsStdLibrary std = RdbmsStdLibrary.INSTANCE;
    
        std.RDBMS_Init();
        std.RDBMS_Shut();
    }


And I got the following stack trace:

java.lang.UnsatisfiedLinkError: Error looking up function 'RDBMS_Init': La procédure spécifiée est introuvable.

    at com.sun.jna.Function.<init>(Function.java:179)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:350)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:330)
    at com.sun.jna.Library$Handler.invoke(Library.java:203)
    at $Proxy6.RDBMS_Init(Unknown Source)

This is really frustrating as it does not seem to be possible to have a simpler function.

I am running this on windows7, DLLs are compiled in 32bits and test is run with a 32bit JVM (1.6.0_06 FWIW), I am running jna 3.4.0. I checked the dll's export table and everything appears to be there.

What am I doing wrong ?

Thanks
Arnaud

Timothy Wall

unread,
Nov 8, 2012, 7:17:14 PM11/8/12
to jna-...@googlegroups.com
Use dependency walker (http://dependencywalker.com) or dumpbin to view the actual symbols in your library.

Chances are it uses the stdcall calling convention and has decorated names; you need to derive from StdCallLibrary and use a StdCallFunctionMapper to automatically map simple names into the decorated versions.

Arnaud Bailly

unread,
Nov 9, 2012, 2:01:49 AM11/9/12
to jna-...@googlegroups.com


On Friday, November 9, 2012 1:17:24 AM UTC+1, Timothy Wall wrote:
Use dependency walker (http://dependencywalker.com) or dumpbin to view the actual symbols in your library.

Chances are it uses the stdcall calling convention and has decorated names; you need to derive from StdCallLibrary and use a StdCallFunctionMapper to automatically map simple names into the decorated versions.


You are surely right: names are mangled in the objdump report. I will check this and report if it works or not.

Thanks a lot for your prompt answer.

Arnaud

Arnaud Bailly

unread,
Nov 9, 2012, 2:21:40 AM11/9/12
to jna-...@googlegroups.com

Hello Timothy,
Here is the output of dumpbin:

Dump of file rdbms_std.dll

File Type: DLL

  Section contains the following exports for rdbms_std.dll

    00000000 characteristics
    509BBD41 time date stamp Thu Nov 08 15:10:09 2012
        0.00 version
           1 ordinal base
           3 number of functions
           3 number of names

    ordinal hint RVA      name

          1    0 00002420 ?RDBMS_Init@@YAXXZ
          2    1 00002450 ?RDBMS_Shut@@YAXXZ
          3    2 00001010 ?RDBMS_pFctGet@@YAPAURDBMS_MXFUNCTION@@XZ

  Summary

        3000 .data
        2000 .rdata
        1000 .reloc
        5000 .text

So names are clearly mangled. Yet with the following modifications to my Java mapped file, it still fails to find the function (and BTW the FunctionMapper is not called):

public interface RdbmsStdLibrary extends StdCallLibrary {

    String JNA_LIBRARY_NAME = "rdbms_std";
    RdbmsStdLibrary INSTANCE = (RdbmsStdLibrary) Native.loadLibrary(RdbmsStdLibrary.JNA_LIBRARY_NAME, //
        RdbmsStdLibrary.class, //
        new HashMap<String, Object>() {

            {
                put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper() {
                        @Override
                        public String getFunctionName(NativeLibrary library, Method method) {
                            String functionName = super.getFunctionName(library, method);
                            System.err.println(String.format("mapping %s to %s", method, functionName));
                            return functionName;
                        }
                    });
            }
        });


    void RDBMS_Init();

    void RDBMS_Shut();

    RdbmsStdLibrary.RDBMS_MXFUNCTION RDBMS_pFctGet();

    public static class RDBMS_MXFUNCTION extends PointerType {
        public RDBMS_MXFUNCTION() {
            super();
        }

        public RDBMS_MXFUNCTION(Pointer address) {
            super(address);
        }
    }
}

I am a little bit more puzzled :-)

Regards,
arnaud

Arnaud Bailly

unread,
Nov 9, 2012, 6:06:59 AM11/9/12
to jna-...@googlegroups.com
So I assume all this got to do with C++ name mangling, right ? JNAerator has support for mapping functions with mangled names, is this support integrated in JNA ?


Thanks
Arnaud

Timothy Wall

unread,
Nov 9, 2012, 7:55:26 AM11/9/12
to jna-...@googlegroups.com
yes, that is C++ name mangling. You can either recompile with 'extern "C"' to avoid mangling, use JNAerator's function mapper, or write your own.
Reply all
Reply to author
Forward
0 new messages