结构的 JNA 非常量字符串成员
JNA non-const String member of struct
我有一个 C 函数需要一个包含非常量字符串的结构。
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 执行此操作的首选方法是什么?
假设您希望它指向您可以写入的任意缓冲区,请使用 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
and W32APIOptions.DEFAULT_OPTIONS
)。
我有一个 C 函数需要一个包含非常量字符串的结构。
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 执行此操作的首选方法是什么?
假设您希望它指向您可以写入的任意缓冲区,请使用 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
and W32APIOptions.DEFAULT_OPTIONS
)。