0

I want to read some functions from a c++ dll in java.

This is a part of the dll code in c++:

typedef void(*E1)(int P1, char * P2);
__declspec(dllimport) void S11(int id, char* P1, E1 callback);
__declspec(dllimport) void Get_P1(int id, char** P1);

And this is the code to read the dll in java:

interface InterestingEvent
{
    public void interestingEvent(int id, String P1);
}

class Callback implements InterestingEvent {
    @Override
    public void interestingEvent(int id, String P1) {
        System.out.print("The the event "+ id + " throw this error: " + P1 + "\n");
    }
}
public class Main{

public interface Kernel32 extends Library {
    public void S11(int id, String P1, InterestingEvent callback);
    public void Get_P1(int id, String[] P1);
    }

public static void main(String[] args) {
    Kernel32 lib = (Kernel32) Native.loadLibrary("path\\to\\dll",
            Kernel32.class);
    lib.S11(id, "some string", new Callback() );
    }
}

And it returns me this error:

Exception in thread "main" java.lang.IllegalArgumentException: Unsupported argument type com.company.Callback at parameter 2 of function S11

what am I doing wrong?

And in the Get_P1 method a value is assigned to the parameter P1 and when return I want it to keep that value, similar to the parameters out in C#. What would be the correct way to invoke this method?

2
  • One level of indirection is understandable to non-C++ apps, since it just means "a pointer to a buffer of T" if the parameter is a T*. However two or more levels of indirection is not so clear cut. What does that char ** supposed to denote? What does the Get_P1 function look like? Commented Apr 27, 2017 at 17:11
  • The Get_P1 function only loads a structure, get a string field and returns it in parameter P1, so the parameter P1 must retain its value similar to the parameters out in C#. Commented Apr 27, 2017 at 17:53

1 Answer 1

1

Your InterestingEvent interface needs to extend JNA's Callback interface (so rename your Callback class to something else). See Callbacks, Function Pointers and Closures for more details.

As for the 2nd parameter of Get_P1(), use PointerByReference instead of String[]. See Using ByReference Arguments for more details. In this case, you can use PointerByReference.getValue() to get a Pointer representing the returned char* value, and then you can convert that to a String using Pointer.getString().

Try this:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Callback;
import com.sun.jna.ptr.PointerByReference;

interface InterestingEvent extends Callback
{
    public void interestingEvent(int id, String P1);
}

class MyCallback implements InterestingEvent {
    @Override
    public void interestingEvent(int id, String P1) {
        System.out.print("The the event "+ id + " throw this error: " + P1 + "\n");
    }
}

public class Main{

    public interface Kernel32 extends Library {
        public void S11(int id, String P1, InterestingEvent callback);
        public void Get_P1(int id, PointerByReference P1);
        }

    public static void main(String[] args) {
        Kernel32 lib = (Kernel32) Native.loadLibrary("path\\to\\dll",
                Kernel32.class);
        lib.S11(id, "some string", new MyCallback() );

        PointerByReference p = new PointerByReference();
        lib.Get_P1(id, p);
        String str = p.getValue().getString(0);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.