JNA 标记联合映射
JNA tagged union mapping
如何将以下 "tagged union" 结构映射到 JNA?此结构由 libvterm
(link to source code) 使用。
/**
* Tagged union storing either an RGB color or an index into a colour palette
*/
typedef union {
/**
* Tag indicating which union member is actually valid. This variable
* coincides with the `type` member of the `rgb` and the `indexed` struct
* in memory. */
uint8_t type;
struct {
uint8_t type;
uint8_t red, green, blue;
} rgb;
struct {
uint8_t type;
uint8_t idx;
} indexed;
} VTermColor;
尽管有许多映射都可以工作(任何具有用于获取值的正确方法的 32 位结构),直接映射它的规范方法是使用 JNA 的 Union class.联盟将具有三个要素;您可以定义的 byte
或结构 RGB
(Union 的内部 class 可以),或者您将定义的结构 Indexed
(同样,一个内部 class)。
Union
将在本机端为最大元素(32 位)分配足够的内存,并且根据结构选项,您可以保证生成的 32 位 C 的前 8 位-side 内存将包含 type
字段;根据该值,您将知道剩余 24 位中包含的内容。
如果您查看 source code of JNA's Variant class which maps the tagged union VARIANT,您会发现它的实现规模稍微复杂一些。 _VARIANT
class 包含这五个元素,类似于 union 中的 3 个元素:
public VARTYPE vt;
public short wReserved1;
public short wReserved2;
public short wReserved3;
public __VARIANT __variant;
对于联合,__variant
只有一个值有效。在这种情况下,类型设置在这里:
public void setVarType(short vt) {
this._variant.vt = new VARTYPE(vt);
}
更一般地说,您可以查看外部 VARIANT
class,它使用 Union class setType()
方法来确定是否存在有效值:它设置对应于在构造函数中设置的活动字段(在本例中为 "_variant"
)的字符串。 (您也可以使用 class 而不是字符串进行设置。)
在您的情况下,您将希望根据类型值进行初始化,因此您将从 type
作为默认值开始,读取其值,然后切换。
您可以这样定义联合:
public class VTermColor extends Union {
public class RGB extends Structure {
public byte type;
public byte red;
public byte green;
public byte blue;
}
public class Indexed extends Structure {
public byte type;
public byte idx;
}
public byte type;
public RGB rgb;
public Indexed indexed;
public VTermColor() {
// initialize knowing only the type, read its value
this.setType("type");
this.read();
// switch union based on type, re-read
if ((this.type & VTERM_COLOR_TYPE_MASK) == VTERM_COLOR_RGB) {
this.setType("rgb");
} else {
this.setType("indexed");
}
this.read();
}
public VTermColor(Pointer p) {
super(p);
// same remaining code as above
}
}
您可能想创建一些其他 getter 方法来在返回适当的字段之前检查 type
值。
如开头所述,任何 32 位数据结构都可以。一个有点 hacky 的替代方案(牺牲可读性和类型安全性以获得更少的代码)可以简单地始终使用上面定义的 4 字节 RGB
结构。 type
的 getter 总是有效,而 red
、green
和 blue
的 getter 如果有效则有效,否则你可以为 idx
创建一个 getter,它只读取 red
.
的值
如何将以下 "tagged union" 结构映射到 JNA?此结构由 libvterm
(link to source code) 使用。
/**
* Tagged union storing either an RGB color or an index into a colour palette
*/
typedef union {
/**
* Tag indicating which union member is actually valid. This variable
* coincides with the `type` member of the `rgb` and the `indexed` struct
* in memory. */
uint8_t type;
struct {
uint8_t type;
uint8_t red, green, blue;
} rgb;
struct {
uint8_t type;
uint8_t idx;
} indexed;
} VTermColor;
尽管有许多映射都可以工作(任何具有用于获取值的正确方法的 32 位结构),直接映射它的规范方法是使用 JNA 的 Union class.联盟将具有三个要素;您可以定义的 byte
或结构 RGB
(Union 的内部 class 可以),或者您将定义的结构 Indexed
(同样,一个内部 class)。
Union
将在本机端为最大元素(32 位)分配足够的内存,并且根据结构选项,您可以保证生成的 32 位 C 的前 8 位-side 内存将包含 type
字段;根据该值,您将知道剩余 24 位中包含的内容。
如果您查看 source code of JNA's Variant class which maps the tagged union VARIANT,您会发现它的实现规模稍微复杂一些。 _VARIANT
class 包含这五个元素,类似于 union 中的 3 个元素:
public VARTYPE vt;
public short wReserved1;
public short wReserved2;
public short wReserved3;
public __VARIANT __variant;
对于联合,__variant
只有一个值有效。在这种情况下,类型设置在这里:
public void setVarType(short vt) {
this._variant.vt = new VARTYPE(vt);
}
更一般地说,您可以查看外部 VARIANT
class,它使用 Union class setType()
方法来确定是否存在有效值:它设置对应于在构造函数中设置的活动字段(在本例中为 "_variant"
)的字符串。 (您也可以使用 class 而不是字符串进行设置。)
在您的情况下,您将希望根据类型值进行初始化,因此您将从 type
作为默认值开始,读取其值,然后切换。
您可以这样定义联合:
public class VTermColor extends Union {
public class RGB extends Structure {
public byte type;
public byte red;
public byte green;
public byte blue;
}
public class Indexed extends Structure {
public byte type;
public byte idx;
}
public byte type;
public RGB rgb;
public Indexed indexed;
public VTermColor() {
// initialize knowing only the type, read its value
this.setType("type");
this.read();
// switch union based on type, re-read
if ((this.type & VTERM_COLOR_TYPE_MASK) == VTERM_COLOR_RGB) {
this.setType("rgb");
} else {
this.setType("indexed");
}
this.read();
}
public VTermColor(Pointer p) {
super(p);
// same remaining code as above
}
}
您可能想创建一些其他 getter 方法来在返回适当的字段之前检查 type
值。
如开头所述,任何 32 位数据结构都可以。一个有点 hacky 的替代方案(牺牲可读性和类型安全性以获得更少的代码)可以简单地始终使用上面定义的 4 字节 RGB
结构。 type
的 getter 总是有效,而 red
、green
和 blue
的 getter 如果有效则有效,否则你可以为 idx
创建一个 getter,它只读取 red
.