WS_UNION_DESCRIPTION
構造体サイズ=各フィールドのバイト数(x64/x86 で異なる場合は x64/x86 と併記)。x64/x86 列=フィールドのバイトオフセット(HSPで dupptr / lpoke / wpoke 等に使用)。
フィールド
| フィールド | 型 | サイズ | x64 | x86 | 説明 |
|---|---|---|---|---|---|
| size | DWORD | 4 | +0 | +0 | 構造体のサイズ (バイト単位) です。 |
| alignment | DWORD | 4 | +4 | +4 | 構造体のアラインメント要件です。これは 1 から 8 までの 2 のべき乗でなければなりません。 |
| fields | WS_UNION_FIELD_DESCRIPTION** | 8/4 | +8 | +8 | 共用体のフィールドの記述へのポインターの配列です。 この配列内のフィールドの順序については、解説セクションを参照してください。 |
| fieldCount | DWORD | 4 | +16 | +12 | fields 配列内のフィールドの数です。フィールドで表現されない構造体の部分は 未初期化のままになります。フィールドの記述は、構造体の同じオフセットを 参照してもかまいません (たとえば、それらがすべて単一の共用体の一部である場合)。 |
| enumOffset | DWORD | 4 | +20 | +16 | 共用体内でどの選択肢が選択されるかを制御する列挙型フィールドのオフセットです。 このフィールドのサイズは、列挙型のサイズ (32 ビット符号付き整数) であると想定されます。 |
| noneEnumValue | INT | 4 | +24 | +20 | この値は、いずれの選択肢も現在設定されていない場合に使用される列挙値に対応します。 このフィールドは、フィールドが省略可能である場合 (WS_FIELD_OPTIONAL が指定された場合) にのみ使用されます。 |
| valueIndices | DWORD* | 8/4 | +32 | +24 | この省略可能な配列は、共用体のフィールドを要素または列挙値によって検索する 際の性能を向上させることができる情報を提供します。この配列は NULL でもかまいません。 その場合は O(n) の検索が使用されますが、フィールド数が少なければ それで十分な場合もあります。 NULL 以外の場合は、次の条件を満たしていなければなりません。
|
公式ドキュメント
共用体型内の選択肢に関する情報です。 これは WS_UNION_TYPE で使用されます。
解説(Remarks)
この記述では、セレクター値 (整数の列挙値) と、可能な選択肢の それぞれに対応するフィールドを含む共用体の両方を持つ構造体を 想定しています。次に例を示します。
// Enumeration of choices of different values
enum Choice
{
ChoiceA = 20,
ChoiceB = 10,
None = 0,
};
// Struct containing union of values, and enum "selector"
struct StructType
{
Choice choice;
union
{
int a;
WS_STRING b;
} value;
};
次の例は、前述の例に対する共用体の記述を初期化する方法を示しています。この例では nameIndices フィールドを設定していますが、このフィールドは代わりに NULL にすることもできます。
WS_XML_STRING choiceAString = WS_XML_STRING_VALUE("choiceA");
WS_XML_STRING choiceANs = WS_XML_STRING_VALUE("http://examples.org/a");
WS_UNION_FIELD_DESCRIPTION fieldA = { };
fieldA.value = ChoiceA;
fieldA.field.localName = &choiceAString;
fieldA.field.ns = &choiceANs;
fieldA.field.type = WS_INT32_TYPE;
fieldA.field.offset = WsOffsetOf(StructType, value.a);
WS_XML_STRING choiceBString = WS_XML_STRING_VALUE("choiceB");
WS_XML_STRING choiceBNs = WS_XML_STRING_VALUE("http://examples.org/b");
WS_UNION_FIELD_DESCRIPTION fieldB = { };
fieldB.value = ChoiceB;
fieldB.field.localName = &choiceBString;
fieldB.field.ns = &choiceBNs;
fieldB.field.type = WS_STRING_TYPE;
fieldB.field.offset = WsOffsetOf(StructType, value.b);
// Sorted by ascending element name (first ns, then localName)
WS_UNION_FIELD_DESCRIPTION* fieldsArray[] =
{
&fieldA, // "http://example.com/a", "choiceA"
&fieldB, // "http://example.com/b", "choiceB"
};
// Sorted by ascending enum value
ULONG valueIndices[] =
{
1, // ChoiceB (10)
0, // ChoiceA (20)
};
WS_UNION_DESCRIPTION unionDescription;
unionDescription.size = sizeof(StructType);
unionDescription.alignment = __alignof(StructType);
unionDescription.fields = fieldsArray;
unionDescription.fieldCount = WsCountOf(fieldsArray);
unionDescription.enumOffset = WsOffsetOf(StructType, choice);
unionDescription.noneEnumValue = None;
unionDescription.valueIndices = valueIndices;
上記により、次のいずれかの要素が出現できるようになります。
<choiceA xmlns="http://example.com/a">123</choiceA>
<choiceB xmlns="http://example.com/b">hello</choiceB>
次は、値を設定する例です。
StructType structType;
// Set ChoiceA
structType.choice = ChoiceA;
structType.value.a = 123;
// Set ChoiceB
static const WS_STRING = WS_STRING_VALUE(L"hello");
structType.choice = ChoiceB;
structType.value.b = helloString;
// Set "none" choice
structType.choice = None;
次は、WS_UNION_DESCRIPTION を構成する WS_FIELD_DESCRIPTION の順序を記述した文法です。順序は WS_FIELD_DESCRIPTION の mapping フィールドに基づいて定義されます。
Fields := ElementContentFields AnyElementField?
ElementContentFields := (ElementField | RepeatingElementField)*
ElementField := WS_ELEMENT_FIELD_MAPPING
RepeatingElementField := WS_REPEATING_ELEMENT_FIELD_MAPPING
AnyElementField := WS_ANY_ELEMENT_FIELD_MAPPING
WS_ELEMENT_FIELD_MAPPING と WS_REPEATING_ELEMENT_FIELD_MAPPING は、要素の選択肢と、共用体内の対応するフィールドを表します。
WS_ANY_ELEMENT_FIELD_MAPPING は、他のどの要素も一致しなかった場合に 使用されるフィールドです。
フィールドの記述には次の制限が適用されます。
- WS_REPEATING_ELEMENT_FIELD_MAPPING は、ラッパー要素の名前と名前空間が 指定されている場合にのみ使用できます。
- WS_FIELD_OPTIONAL は使用できません。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での定義
#include <windows.h>
// WS_UNION_DESCRIPTION (x64 40 / x86 28 バイト)
typedef struct WS_UNION_DESCRIPTION {
DWORD size;
DWORD alignment;
WS_UNION_FIELD_DESCRIPTION** fields;
DWORD fieldCount;
DWORD enumOffset;
INT noneEnumValue;
DWORD* valueIndices;
} WS_UNION_DESCRIPTION;using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WS_UNION_DESCRIPTION
{
public uint size;
public uint alignment;
public IntPtr fields;
public uint fieldCount;
public uint enumOffset;
public int noneEnumValue;
public IntPtr valueIndices;
}Imports System.Runtime.InteropServices
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure WS_UNION_DESCRIPTION
Public size As UInteger
Public alignment As UInteger
Public fields As IntPtr
Public fieldCount As UInteger
Public enumOffset As UInteger
Public noneEnumValue As Integer
Public valueIndices As IntPtr
End Structureimport ctypes
from ctypes import wintypes
class WS_UNION_DESCRIPTION(ctypes.Structure):
_fields_ = [
("size", wintypes.DWORD),
("alignment", wintypes.DWORD),
("fields", ctypes.c_void_p),
("fieldCount", wintypes.DWORD),
("enumOffset", wintypes.DWORD),
("noneEnumValue", ctypes.c_int),
("valueIndices", ctypes.c_void_p),
]#[repr(C)]
pub struct WS_UNION_DESCRIPTION {
pub size: u32,
pub alignment: u32,
pub fields: *mut core::ffi::c_void,
pub fieldCount: u32,
pub enumOffset: u32,
pub noneEnumValue: i32,
pub valueIndices: *mut core::ffi::c_void,
}import "golang.org/x/sys/windows"
type WS_UNION_DESCRIPTION struct {
size uint32
alignment uint32
fields uintptr
fieldCount uint32
enumOffset uint32
noneEnumValue int32
valueIndices uintptr
}type
WS_UNION_DESCRIPTION = record
size: DWORD;
alignment: DWORD;
fields: Pointer;
fieldCount: DWORD;
enumOffset: DWORD;
noneEnumValue: Integer;
valueIndices: Pointer;
end;const WS_UNION_DESCRIPTION = extern struct {
size: u32,
alignment: u32,
fields: ?*anyopaque,
fieldCount: u32,
enumOffset: u32,
noneEnumValue: i32,
valueIndices: ?*anyopaque,
};type
WS_UNION_DESCRIPTION {.bycopy.} = object
size: uint32
alignment: uint32
fields: pointer
fieldCount: uint32
enumOffset: uint32
noneEnumValue: int32
valueIndices: pointerstruct WS_UNION_DESCRIPTION
{
uint size;
uint alignment;
void* fields;
uint fieldCount;
uint enumOffset;
int noneEnumValue;
void* valueIndices;
}HSP用 定義
HSP3.7/3.8 は構造体機能が無いため4byte整数配列(dim)+peek/poke で操作(32/64bitでサイズ・位置が異なる場合はタブで分割)。IronHSP は NSTRUCT(#defstruct/stdim/->)で32/64bit共通。
; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x86 レイアウト)
; WS_UNION_DESCRIPTION サイズ: 28 バイト(x86)
dim st, 7 ; 4byte整数×7(構造体サイズ 28 / 4 切り上げ)
; size : DWORD (+0, 4byte) st.0 = 値 / 値 = st.0 (lpoke/lpeek も可)
; alignment : DWORD (+4, 4byte) st.1 = 値 / 値 = st.1 (lpoke/lpeek も可)
; fields : WS_UNION_FIELD_DESCRIPTION** (+8, 4byte) varptr(st)+8 を基点に操作(4byte:入れ子/配列)
; fieldCount : DWORD (+12, 4byte) st.3 = 値 / 値 = st.3 (lpoke/lpeek も可)
; enumOffset : DWORD (+16, 4byte) st.4 = 値 / 値 = st.4 (lpoke/lpeek も可)
; noneEnumValue : INT (+20, 4byte) st.5 = 値 / 値 = st.5 (lpoke/lpeek も可)
; valueIndices : DWORD* (+24, 4byte) st.6 = 値 / 値 = st.6 (lpoke/lpeek も可)
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x64 レイアウト)
; WS_UNION_DESCRIPTION サイズ: 40 バイト(x64)
dim st, 10 ; 4byte整数×10(構造体サイズ 40 / 4 切り上げ)
; size : DWORD (+0, 4byte) st.0 = 値 / 値 = st.0 (lpoke/lpeek も可)
; alignment : DWORD (+4, 4byte) st.1 = 値 / 値 = st.1 (lpoke/lpeek も可)
; fields : WS_UNION_FIELD_DESCRIPTION** (+8, 8byte) varptr(st)+8 を基点に操作(8byte:入れ子/配列)
; fieldCount : DWORD (+16, 4byte) st.4 = 値 / 値 = st.4 (lpoke/lpeek も可)
; enumOffset : DWORD (+20, 4byte) st.5 = 値 / 値 = st.5 (lpoke/lpeek も可)
; noneEnumValue : INT (+24, 4byte) st.6 = 値 / 値 = st.6 (lpoke/lpeek も可)
; valueIndices : DWORD* (+32, 8byte) qpoke st,32,値 / qpeek(st,32) ※IronHSPのみ。3.7/3.8は lpoke st,32,下位 : lpoke st,36,上位
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。; IronHSP は NSTRUCT(構造体)をサポート。32bit/64bit どちらでも同じコードで動作します。
#defstruct global WS_UNION_DESCRIPTION
#field int size
#field int alignment
#field intptr fields
#field int fieldCount
#field int enumOffset
#field int noneEnumValue
#field intptr valueIndices
#endstruct
stdim st, WS_UNION_DESCRIPTION ; NSTRUCT 変数を確保
st->size = 100
mes "size=" + st->size