我有以下代码:
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!)
一些提示?
答案 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 *类型...... 你觉得怎么样?
再见