Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

renaming DLL functions in JNA using StdCallFunctionMapper

Tags:

java

dll

jna

I'm trying to use JNA with a DLL in Windows, so far I was able to successfully call a function called c_aa_find_devices(). But all the functions start with c_aa and I would like to rename it to find_devices().

From what I gather the way to do this is with StdCallFunctionMapper but I can't find the documentation of how to use it in an example (i.e. how to map a DLL function by name or by ordinal to a desired name in the wrapped Java library interface). Any suggestions on where the docs are?

like image 705
Jason S Avatar asked Feb 05 '09 21:02

Jason S


3 Answers

A complete working example, using a function mapper.

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.win32.StdCallFunctionMapper;

import java.io.File;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class JnaTest {


    static {
    Map options = new HashMap();
        options.
                put(
                        Library.OPTION_FUNCTION_MAPPER,
                        new StdCallFunctionMapper() {
                            HashMap<String, String> map = new HashMap() {
                                {
                                    put("testMethod", "testMethod@0");
                                }
                            };
                            @Override
                            public String getFunctionName(NativeLibrary library, Method method) {
                                String methodName = method.getName();
                                return map.get(methodName);

                            }
                        }
                );

        File LIB_FILE = new File("test.dll");
        Native.register(NativeLibrary.getInstance(LIB_FILE.getAbsolutePath(), options));

    }

    private static native int testMethod();

    public static void main(String[] args) {
        testMethod(); // call the native method in the loaded dll with the function name testMethod@0
    }


}
like image 100
Ekkelenkamp Avatar answered Nov 11 '22 00:11

Ekkelenkamp


Using StdCallMapper won't do good - it is supposed to map werid windows std lib names that have embedded total byte lenght of parameters embedded as part of the name. Since it is done to std lib only (just guessing on that, but 99% you'r functions are not the case).

If your dll uses some common prefix on all functions you need just to use something like:

class Mapper implements FunctionMapper{
    public String getFunctionName(NativeLibrary library, Method method) {
       return GenieConnector.FUNCTION_PREFIX + method.getName();
    }
}

Where GenieConnector.FUNCTION_PREFIX is that common prefix. Bear in mind that i implement FunctionMapper, not extend StdCallMapper

like image 4
jb. Avatar answered Nov 10 '22 22:11

jb.


From the documentation you need to provide a FunctionMapper in the original call to loadLibrary that converts the name. However you also need to keep the standard call mapping so try something like the following:

Map options = new HashMap();

options.
    put(
        Library.OPTION_FUNCTION_MAPPER, 
        new StdCallFunctionWrapper() {
            public String getFunctionName(NativeLibrary library, Method method) {
                if (method.getName().equals("findDevices") 
                    method.setName("c_aa_find_devices");
                // do any others
                return super.getFunctionName(library, method);
            }
        }
    );

Native.loadLibrary(..., ..., options);
like image 2
Michael Rutherfurd Avatar answered Nov 10 '22 23:11

Michael Rutherfurd