我使用JNA从java调用c函数。该函数将字符串列表写入用户提供的内存,其签名为:
void c_getStrings(char *buf, size_t bufSize, char *strings[], size_t *stringsCount)
使用Java版本:
public interface TestCaseDLL extends Library
{
int c_getStrings(byte[] buf, int bufSize, Memory strings, IntByReference stringCount);
}
public class TestCase
{
public static void main(String[] args)
{
byte[] buf = new byte[100];
Memory strings = new Memory(Memory.SIZE * 10);
IntByReference stringCount = new IntByReference(10);
// c_getStrings() will write the strings continuously to 'buf' and
// additionally return a list of starting addresses through the
// 'strings' parameter (that is 'strings' point into 'buf').
// 'stringCount' holds the initial array size of 'strings' and will
// return the count of returned strings.
TestCaseDLL.INSTANCE.c_getStrings(buf, buf.length, strings, stringCount);
System.out.println(strings.getPointer(0).getString(0));
System.out.printf("%c\n", buf[0]); // how can this line change 'strings'?
System.out.println(strings.getPointer(0).getString(0));
for (byte b: buf) {
System.out.print((char) b);
}
System.out.println("");
for (byte b: buf) {
System.out.printf("%#x ", b);
}
System.out.println("");
}
}
输出
??llo world!
H
?
Hello world! Hallo Welt! Ciao a tutti!
0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x21 0x0 0x48 0x61 0x6c 0x6c 0x6f 0x20 0x57 0x65 0x6c 0x74 0x21 0x0 0x43 0x69 0x61 0x6f 0x20 0x61 0x20 0x74 0x75 0x74 0x74 0x69 0x21 0x0 ...
我遇到了以下问题:
buf[0]
会更改返回的字符串。我现在已经知道这里发生了什么,因为我只是在阅读它的价值。我的类型映射是否已损坏,或者我遗漏了哪些基本信息?
更新
我现在使用
void c_getStrings(Memory buf, int bufSize, String[] strings, IntByReference stringCount);
如果我要重做它,我会把它分成两个函数,如technomage建议的那样:
void c_fill(char *buf, size_t bufSize);
void c_parseToStringArray(const char *buf, const char *strings[], size_t stringsSize);
答案 0 :(得分:1)
前几个技术要点:
Memory
。但是,如果您只需要生成的String
值并且不关心指针本身,那么byte[]
,NIO缓冲区或Memory
将起作用,前提是第三个参数是输入String[]
。Pointer[]
或String[]
。你也可以使用Memory
,只要它被分配得足够大,可以保存尽可能多的指针值。然后是更大的问题:
String[]
第三个参数获取字符串后就不需要它了。如果您打算在缓冲区中操作内容,则此类更改不会反映在“返回”字符串中。