我有一个C函数,它需要一个包含非const String的结构。
typedef struct _A {
char* str;
} A;
void myFunc(A* aptr) { ... }
我已经尝试了很长时间通过JNA传递这个东西,但到目前为止还没有管理。
public class A extends Structure {
public String str;
protected List getFieldOrder() { ...
}
不起作用,因为String将变为const char *而不是我需要的char *。
public class A extends Structure {
public byte[] str;
protected List getFieldOrder() { ...
}
不起作用,因为结构中的字节数组变成了连续的内存,而不是指针。
我知道我可以使用Memory
并复制字符串来完成。但我无法想象这是做这件事的首选方式。
我也试过像
这样的东西public class NonConstStringMember extends Structure {
public static class ByReference extends NonConstStringMember implements Structure.ByReference {}
public byte[] stringMember;
protected List getFieldOrder() { ...
}
public class A extends Structure {
public NonConstStringMember.ByReference str;
}
但它也不起作用,可能是因为对齐问题。
使用JNA执行此操作的首选方法是什么?
答案 0 :(得分:2)
假设您希望它指向您可以写入的任意缓冲区,请使用Pointer
(如果您正在分配缓冲区,则为其分配Memory
值。
然后使用Pointer.getString(0)
或Pointer.setString(0, s)
来操作缓冲区内容。
修改强>
Windows库通常具有大多数函数的ascii或unicode版本。虽然在大多数情况下您可以定义单个Structure
以便在两种情况下使用,但有时您需要提供一些额外的处理以确保使用正确的类型。由于这两种模式很少(如果有的话)同时使用,因此JNA将选项设置为默认为一个或另一个(自动映射到右侧函数后缀,并自动将String
映射到本机const char*
或const wchar_t*
取决于模式。)
如果使用unicode模式,则使用setWideString()
,否则使用setString()
,或者在Structure
上设置一些访问者以自动处理。例如:
class MyStructure extends Structure {
private static final boolean ASCII = Boolean.getBoolean("w32.ascii");
public Pointer stringBuffer = new Memory(X);
void setStringBuffer(String s) {
stringBuffer.setString(0, s, ASCII);
}
String getStringBuffer() {
return stringBuffer.getString(0, ASCII);
}
}
修改强>
请注意,在大多数情况下,您应使用String
作为字段类型,并依赖TypeMapper
在适当的幕后使用WString
(例如User32
和{{ 3}})。