Java:使用char **加载c ++ dll并将callback作为参数加载

时间:2017-04-27 16:44:55

标签: java c++ dll jna

我想从java中的c ++ dll中读取一些函数。

这是c ++中dll代码的一部分:

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);

这是在java中读取dll的代码:

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() );
    }
}

它返回给我这个错误:

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

我做错了什么?

在Get_P1方法中,一个值被赋值给参数P1,当返回时我希望它保持该值,类似于C#中的参数。调用此方法的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

您的InterestingEvent界面需要扩展JNA的Callback界面(因此请将您的Callback类重命名为其他内容)。有关详细信息,请参阅Callbacks, Function Pointers and Closures

至于Get_P1()的第二个参数,请使用PointerByReference代替String[]。有关详细信息,请参阅Using ByReference Arguments。在这种情况下,您可以使用PointerByReference.getValue()获取表示返回的char*值的Pointer,然后使用Pointer.getString()将其转换为String

试试这个:

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);
    }
}