JNA - 尝试使用void * param访问C函数时VM崩溃

时间:2012-10-02 18:53:29

标签: java c jna

我有以下代码:

public class TTM {

public interface WrapperDLL extends Library {
    WrapperDLL INSTANCE = (WrapperDLL) Native.loadLibrary("TransportRE", WrapperDLL.class);

    int TRE_send(int channel, Pointer data, int len);

}
public int Send (int channel, String data, int len) {
    WrapperDLL wdll = WrapperDLL.INSTANCE;

    Memory mem = new Memory(data.length()+1);
    mem.setString(0, data);
    int byteSent = wdll.TRE_send(channel_id, mem.getPointer(0), len);
    // at this (TRE_send) point the VM crashes !!!!

  return byteSent;
}

}

看一下我试过的JNA api:

public int Send (int channel, String data, int len) {
    WrapperDLL wdll = WrapperDLL.INSTANCE;

    Memory mem = new Memory(data.length()+1);
    mem.setString(0, data);
    int byteSent = wdll.TRE_send(channel_id, mem, len);

  return byteSent;
}

此时不会崩溃,但无法正常工作(byteSent = 0!)

一些提示?

2 个答案:

答案 0 :(得分:1)

您正在取消引用您的String,就好像它包含指针而不是字符数据。

Pointer.getPointer(0)尝试从给定的指针地址中提取指针值;你肯定想直接传递指针值,就像你的第二个片段一样。

JNA允许您直接传递String值,自动将其转换为C字符串(NUL终止的字节数组)。但是,您的本机方法需要字符串并不清楚;它可能需要一个特殊格式的字节缓冲区。

如果len是您要发送的缓冲区的长度,那么它应该是字符串的长度加上一个(或者您传递的Memory的大小) )。

修改

你暗示DLL总是强制转换为char *,在这种情况下你应该按原样传递String。如果您的DLL有时需要非ASCII数据,那么您应该传递Memory并使用其成员函数来编写所需的数据。请注意,您可以使用不同的签名定义DLL的多个版本,例如

  void send(String);
  void send(Pointer);
  void send(MyStructure);

答案 1 :(得分:0)

我已修好了!

int byteSent = wdll.TRE_send(channel_id, data.toCharArray(), len);

因为第二个参数是一个void *但是在dll代码中,第一个是将它转换为char *我使用相同的类型,现在它可以工作。

肯定这不是“一般解决方案”,因为“TRE_send”想要一个void *类型...... 你觉得怎么样?

再见