0

I'm complete Java ignorant, yet I've to resolve this problem. I'm using JNA and have in one file:

public interface JRockey4ND extends Library {

    public short rockey(short func, short[] handle, int[] lp1, int[] lp2, short[] p1, short[] p2, short[] p3, short[] p4, byte[] buffer);
    public short RY_FIND=1;
    public short RY_FIND_NEXT=2;
}

and in another file:

JRockey4ND rockey = (JRockey4ND) Native.loadLibrary(libFileName, JRockey4ND.class);
.
.
retval=rockey.rockey(rockey.RY_FIND,handle[0],lp1,lp2,p1,p2,p3,p4,buffer);

and it works like a charm. But depending on platform, I have to use Rockey method instead of rockey due to exported symbols naming mismatch between Linux .so and Windows .dll. I've tried to replace symbol name in so file by using: perl -pi -e 's/rockey/Rockey/g' lib.so but it doesn't work ( symbol 'Rockey' can't be found after that, despite of replacement ).

So my question is, how this can be resolved programmatically in easiest possible way ( not the prettiest one ). Many thanks!

pikkewyn
  • 181
  • 1
  • 8
  • In this case you probably don't want to be trying to control the capitalization of symbols exported from libraries. Why not perform a check for which OS you're running and make the appropriate call? See http://stackoverflow.com/questions/228477/how-do-i-programmatically-determine-operating-system-in-java – Jonathan Ellithorpe Mar 01 '16 at 14:43
  • 1
    You could try and use reflection, e.g. depending on the OS you look for the method "rockey" or "Rockey" in `JRockey4ND.class`. – Thomas Mar 01 '16 at 14:44
  • Thanks @Thomas, sounds very good. But how should I modify my interface so it will be able to provide both methods? I can't just check OS directly in body of interface. – pikkewyn Mar 01 '16 at 16:46
  • Hmm, I'd probably not change the interface but check the implementation class returned by the `loadLibrary` call, i.e. use `rockey.getClass()` to get it. Then use `getMethod("rockey", )` to get the lower case method. If it doesn't exist, i.e. you get a `MethodNotFoundException`, try with method name `"Rockey"` then. However, the problem is that I didn't use JNA for a while so I don't know whether you can load the library at all if the method names don't fit. If that's the case then you'd probably be better off solving the case problem. – Thomas Mar 01 '16 at 17:28
  • Is `Rockey` a 3rd party library? If so, is there a way to recompile it and change the names during symbol generation/export? If not, you might try and write an adapter that provides the method names in the correct case and delegates the calls to the actual library. – Thomas Mar 01 '16 at 17:30

1 Answers1

2

According to the JNA JavaDoc, you can provide a FunctionMapper as an option when initializing your library which maps the method name to the library name.

FunctionMapper mapper = new FunctionMapper() {
    public String getFunctionName(NativeLibrary library, Method method) {
    if (Platform.isWindows()) {
        if (method.getName().equals("rocket")) {
            return "Rocket";
        }
    }
    return method.getName();

} }; Map options = new HashMap(); options.put(Library.OPTION_FUNCTION_MAPPER, mapper); Native.loadLibrary("rocket", Rocket.class, options);

technomage
  • 9,861
  • 2
  • 26
  • 40