ส่วนนี้จะอธิบายประเภทข้อมูล HIDL ดูรายละเอียดการใช้งานได้ที่ HIDL C++ (สําหรับการใช้งาน C++) หรือ HIDL Java (สําหรับการใช้งาน Java)
ลักษณะที่คล้ายกับ C++ มีดังนี้
structs
ใช้ไวยากรณ์ C++unions
รองรับไวยากรณ์ C++ โดยค่าเริ่มต้น โครงสร้างและยูเนียนทั้ง 2 รายการต้องมีชื่อ โดยระบบไม่รองรับโครงสร้างและยูเนียนที่ไม่มีชื่อ- อนุญาตให้ใช้ Typedef ใน HIDL (เช่นเดียวกับใน C++)
- ระบบจะอนุญาตความคิดเห็นสไตล์ C++ และคัดลอกความคิดเห็นดังกล่าวไปยังไฟล์ส่วนหัวที่สร้างขึ้น
ลักษณะที่คล้ายกับ Java มีดังนี้
- HIDL จะกำหนดเนมสเปซสไตล์ Java ให้กับแต่ละไฟล์ ซึ่งต้องขึ้นต้นด้วย
android.hardware.
เนมสเปซ C++ ที่สร้างขึ้นคือ::android::hardware::…
- คําจํากัดความทั้งหมดของไฟล์จะอยู่ใน Wrapper สไตล์ Java
interface
- การประกาศอาร์เรย์ HIDL เป็นไปตามสไตล์ Java ไม่ใช่สไตล์ C++ ตัวอย่าง
struct Point { int32_t x; int32_t y; }; Point[3] triangle; // sized array
- ความคิดเห็นคล้ายกับรูปแบบ Javadoc
การนําเสนอข้อมูล
struct
หรือ union
ที่ประกอบไปด้วยเลย์เอาต์มาตรฐาน (ชุดย่อยของข้อกำหนดของประเภทข้อมูลแบบเดิม) มีเลย์เอาต์หน่วยความจำที่สอดคล้องกันในโค้ด C++ ที่สร้างขึ้น ซึ่งบังคับใช้ด้วยแอตทริบิวต์การจัดแนวที่ชัดเจนในสมาชิก struct
และ union
ประเภท HIDL พื้นฐาน รวมถึงประเภท enum
และ bitfield
(ซึ่งมาจากประเภทพื้นฐานเสมอ) จะแมปกับประเภท C++ มาตรฐาน เช่น std::uint32_t
จาก cstdint
เนื่องจาก Java ไม่รองรับประเภทที่ไม่มีค่าลงนาม ระบบจะแมปประเภท HIDL ที่ไม่มีค่าลงนามกับประเภท Java ที่มีค่าลงนามที่สอดคล้องกัน Structs จะแมปกับคลาส Java ส่วนอาร์เรย์จะแมปกับอาร์เรย์ Java ขณะนี้ระบบยังไม่รองรับยูเนียนใน Java ระบบจะจัดเก็บสตริงภายในเป็น UTF8 เนื่องจาก Java รองรับเฉพาะสตริง UTF16 ค่าสตริงที่ส่งไปยังหรือจากการใช้งาน Java จึงได้รับการแปล และอาจไม่เหมือนกันเมื่อแปลอีกครั้งเนื่องจากชุดอักขระไม่จับคู่กันเสมอไป
ข้อมูลที่รับผ่าน IPC ใน C++ จะมีเครื่องหมาย const
และอยู่ในหน่วยความจําแบบอ่านอย่างเดียวที่จะคงอยู่ตลอดระยะเวลาที่เรียกใช้ฟังก์ชันเท่านั้น ระบบได้คัดลอกข้อมูลที่รับผ่าน IPC ใน Java ไปยังออบเจ็กต์ Java แล้ว จึงเก็บข้อมูลไว้ได้โดยไม่ต้องคัดลอกเพิ่มเติม (และสามารถแก้ไขได้)
คำอธิบายประกอบ
คุณสามารถเพิ่มคำอธิบายประกอบสไตล์ Java ในการประกาศประเภท แบ็กเอนด์ของชุดทดสอบ Vendor (VTS) ของคอมไพเลอร์ HIDL จะแยกวิเคราะห์คำอธิบายประกอบ แต่คอมไพเลอร์ HIDL จะไม่เข้าใจคำอธิบายประกอบที่แยกวิเคราะห์ดังกล่าว แต่ VTS Compiler (VTSC) จะจัดการคำอธิบายประกอบ VTS ที่แยกวิเคราะห์แล้วแทน
คําอธิบายประกอบใช้ไวยากรณ์ Java: @annotation
หรือ
@annotation(value)
หรือ @annotation(id=value, id=value…)
โดยที่ค่าอาจเป็นนิพจน์คงที่ สตริง หรือรายการค่า
ภายใน {}
เช่นเดียวกับใน Java คุณแนบคำอธิบายประกอบที่มีชื่อเดียวกันหลายรายการในรายการเดียวกันได้
การประกาศการส่งต่อ
ใน HIDL คุณอาจประกาศโครงสร้างล่วงหน้าไม่ได้ ซึ่งทำให้ไม่สามารถใช้ประเภทข้อมูลที่อ้างอิงตนเองที่ผู้ใช้กำหนด (เช่น คุณไม่สามารถอธิบายลิงค์ลิสต์หรือต้นไม้ใน HIDL ได้) HAL ที่มีอยู่ส่วนใหญ่ (ก่อน Android 8.x) ใช้การประกาศล่วงหน้าอย่างจำกัด ซึ่งสามารถนําออกได้โดยการเรียงลําดับการประกาศโครงสร้างข้อมูลใหม่
ข้อจํากัดนี้ช่วยให้สามารถคัดลอกโครงสร้างข้อมูลตามค่าด้วยการคัดลอกเชิงลึกแบบง่ายได้ แทนที่จะติดตามค่าพอยน์เตอร์ที่อาจเกิดขึ้นหลายครั้งในโครงสร้างข้อมูลที่อ้างอิงตนเอง หากมีการส่งข้อมูลเดียวกัน 2 ครั้ง เช่น พารามิเตอร์เมธอดหรือ vec<T>
2 รายการที่ชี้ไปยังข้อมูลเดียวกัน ระบบจะสร้างและส่งสำเนาแยกกัน 2 รายการ
การประกาศที่ซ้อนกัน
HIDL รองรับการประกาศที่ซ้อนกันในระดับต่างๆ ได้มากเท่าที่ต้องการ (มีข้อยกเว้น 1 ข้อที่ระบุไว้ด้านล่าง) เช่น
interface IFoo { uint32_t[3][4][5][6] multidimArray; vec<vec<vec<int8_t>>> multidimVector; vec<bool[4]> arrayVec; struct foo { struct bar { uint32_t val; }; bar b; } struct baz { foo f; foo.bar fb; // HIDL uses dots to access nested type names } …
ข้อยกเว้นคือประเภทอินเทอร์เฟซจะฝังได้ใน vec<T>
เท่านั้นและฝังได้เพียง 1 ระดับ (ไม่มี vec<vec<IFoo>>
)
ไวยากรณ์ของพอยน์เตอร์ดิบ
ภาษา HIDL ไม่ได้ใช้ * และไม่รองรับความยืดหยุ่นทั้งหมดของพอยน์เตอร์ดิบ C/C++ ดูรายละเอียดเกี่ยวกับวิธีที่ HIDL บรรจุข้อมูลชี้และอาร์เรย์/เวกเตอร์ได้ที่เทมเพลต vec<T>
อินเทอร์เฟซ
คีย์เวิร์ด interface
มีการใช้งาน 2 แบบ
- โดยจะเปิดคําจํากัดความของอินเทอร์เฟซในไฟล์ .hal
- สามารถใช้เป็นประเภทพิเศษในช่อง struct/union, พารามิเตอร์ของเมธอด และผลลัพธ์ อินเทอร์เฟซนี้ถือเป็นอินเทอร์เฟซทั่วไปและเป็นคำพ้องกับ
android.hidl.base@1.0::IBase
เช่น IServiceManager
มีเมธอดต่อไปนี้
get(string fqName, string name) generates (interface service);
เมธอดนี้สัญญาว่าจะค้นหาอินเทอร์เฟซบางรายการตามชื่อ และเหมือนกับการแทนที่อินเทอร์เฟซด้วย android.hidl.base@1.0::IBase
อินเทอร์เฟซสามารถส่งได้ 2 วิธีเท่านั้น ได้แก่ ใช้เป็นพารามิเตอร์ระดับบนสุด หรือใช้เป็นสมาชิกของ vec<IMyInterface>
แต่จะไม่สามารถเป็นสมาชิกของ vec, โครงสร้าง, อาร์เรย์ หรือยูเนียนที่ฝังอยู่
MQDescriptorSync และ MQDescriptorUnsync
ประเภท MQDescriptorSync
และ MQDescriptorUnsync
จะส่งข้อบ่งชี้คิวข้อความด่วน (FMQ) แบบซิงค์หรือไม่ซิงค์ผ่านอินเทอร์เฟซ HIDL โปรดดูรายละเอียดที่ HIDL C++ (Java ไม่รองรับ FMQ)
ประเภทหน่วยความจำ
ประเภท memory
ใช้เพื่อแสดงหน่วยความจำที่แชร์ซึ่งไม่ได้แมปใน HIDL รองรับเฉพาะใน C++ ค่าประเภทนี้สามารถใช้ที่ฝั่งที่รับเพื่อเริ่มต้นออบเจ็กต์ IMemory
, แมปหน่วยความจำ และทำให้ใช้งานได้ โปรดดูรายละเอียดที่ HIDL C++
คําเตือน: Structured Data ที่วางไว้ในหน่วยความจําที่ใช้ร่วมกันต้องเป็นประเภทที่รูปแบบจะไม่เปลี่ยนแปลงตลอดอายุการใช้งานของเวอร์ชันอินเทอร์เฟซที่ส่ง memory
มิเช่นนั้น HAL อาจประสบปัญหาความเข้ากันได้ร้ายแรง
ประเภทเคอร์เซอร์
ประเภท pointer
มีไว้สำหรับใช้ภายในของ HIDL เท่านั้น
เทมเพลตประเภท bitfield<T>
bitfield<T>
โดยที่ T
เป็น enum ที่ผู้ใช้กำหนด บ่งบอกว่าค่านั้นเป็น OR แบบบิตของค่า enum ที่กําหนดไว้ใน T
ในโค้ดที่สร้างขึ้น bitfield<T>
จะปรากฏเป็นประเภทพื้นฐานของ T เช่น
enum Flag : uint8_t { HAS_FOO = 1 << 0, HAS_BAR = 1 << 1, HAS_BAZ = 1 << 2 }; typedef bitfield<Flag> Flags; setFlags(Flags flags) generates (bool success);
คอมไพเลอร์จะจัดการ Flags ประเภทเดียวกับ uint8_t
เหตุใดจึงไม่ใช้ (u)int8_t
/(u)int16_t
/(u)int32_t
/(u)int64_t
การใช้ bitfield
จะให้ข้อมูลเพิ่มเติมเกี่ยวกับ HAL แก่ผู้อ่าน ซึ่งตอนนี้ทราบว่า setFlags
ใช้ค่า OR แบบบิตของ Flag (กล่าวคือ ทราบว่าการเรียกใช้ setFlags
ด้วย 16 ไม่ถูกต้อง) หากไม่มี
bitfield
ระบบจะส่งข้อมูลนี้ผ่านเอกสารประกอบเท่านั้น นอกจากนี้ VTS ยังตรวจสอบได้ว่าค่าของ Flag เป็น OR แบบบิตของ Flag หรือไม่
แฮนเดิลประเภทพื้นฐาน
คำเตือน: ที่อยู่ทุกประเภท (แม้แต่ที่อยู่ของอุปกรณ์จริง) ต้องไม่เป็นส่วนหนึ่งของแฮนเดิลเนทีฟ การส่งข้อมูลนี้ระหว่างกระบวนการต่างๆ เป็นอันตรายและทำให้กระบวนการเหล่านั้นเสี่ยงต่อการถูกโจมตี ค่าที่ส่งผ่านระหว่างกระบวนการต้องได้รับการตรวจสอบก่อนนำไปใช้เพื่อค้นหาหน่วยความจำที่จองภายในกระบวนการ มิฉะนั้น แฮนเดิลที่ไม่ถูกต้องอาจทําให้เกิดการเข้าถึงหน่วยความจําที่ไม่ถูกต้องหรือหน่วยความจําเสียหาย
ความหมายของ HIDL เป็นแบบคัดลอกตามค่า ซึ่งหมายความว่าจะมีการคัดลอกพารามิเตอร์
ระบบจะจัดการข้อมูลขนาดใหญ่หรือข้อมูลที่จําเป็นต้องแชร์ระหว่างกระบวนการ (เช่น รั้วการซิงค์) โดยการนําส่งตัวระบุไฟล์ที่ชี้ไปยังออบเจ็กต์ถาวร ashmem
สําหรับหน่วยความจําที่ใช้ร่วมกัน ไฟล์จริง หรือสิ่งอื่นๆ ที่สามารถซ่อนอยู่หลังตัวระบุไฟล์ โปรแกรมควบคุม Binder จะทําสําเนาตัวระบุไฟล์ไปยังกระบวนการอื่น
native_handle_t
Android รองรับ native_handle_t
ซึ่งเป็นแนวคิดแฮนเดิลทั่วไปที่ระบุไว้ใน libcutils
typedef struct native_handle { int version; /* sizeof(native_handle_t) */ int numFds; /* number of file-descriptors at &data[0] */ int numInts; /* number of ints at &data[numFds] */ int data[0]; /* numFds + numInts ints */ } native_handle_t;
แฮนเดิลเนทีฟคือคอลเล็กชันของ int และตัวระบุไฟล์ที่ส่งต่อกันตามค่า คุณสามารถจัดเก็บตัวระบุไฟล์รายการเดียวในตัวแฮนเดิลแบบเนทีฟโดยไม่มี int และตัวระบุไฟล์รายการเดียว การส่งแฮนเดิลโดยใช้แฮนเดิลเนทีฟที่รวมอยู่ในhandle
ประเภทพื้นฐานช่วยให้มั่นใจว่าแฮนเดิลเนทีฟจะรวมอยู่ใน HIDL โดยตรง
เนื่องจาก native_handle_t
มีขนาดใหญ่แบบแปรผัน จึงรวมไว้ในโครงสร้างโดยตรงไม่ได้ ช่องแฮนเดิลจะสร้างพอยน์เตอร์ไปยัง native_handle_t
ที่จัดสรรแยกต่างหาก
ใน Android เวอร์ชันเก่า ระบบจะสร้างแฮนเดิลแบบเนทีฟโดยใช้ฟังก์ชันเดียวกันกับที่มีอยู่ใน libcutils
ใน Android 8.0 ขึ้นไป ระบบจะคัดลอกฟังก์ชันเหล่านี้ไปยังเนมสเปซ android::hardware::hidl
หรือย้ายไปยัง NDK โค้ด HIDL ที่สร้างขึ้นโดยอัตโนมัติจะจัดรูปแบบและถอดรูปแบบฟังก์ชันเหล่านี้โดยอัตโนมัติโดยที่ไม่ต้องอาศัยโค้ดที่ผู้ใช้เขียน
การเป็นเจ้าของแฮนเดิลและตัวระบุไฟล์
เมื่อคุณเรียกใช้เมธอดอินเทอร์เฟซ HIDL ที่ส่ง (หรือแสดงผล) hidl_handle
ออบเจ็กต์ (ระดับบนสุดหรือเป็นส่วนหนึ่งของประเภทคอมโพเนนต์) ความเป็นเจ้าของของไฟล์ที่ระบุที่อยู่ในนั้นจะเป็นดังนี้
- ผู้เรียกที่ส่งออบเจ็กต์
hidl_handle
เป็นอาร์กิวเมนต์จะยังคงเป็นเจ้าของตัวระบุไฟล์ที่อยู่ในnative_handle_t
ที่รวมอยู่ด้วย ผู้เรียกต้องปิดตัวระบุไฟล์เหล่านี้เมื่อดำเนินการเสร็จแล้ว - กระบวนการที่แสดงผลออบเจ็กต์
hidl_handle
(โดยการส่งไปยังฟังก์ชัน_cb
) จะยังคงเป็นเจ้าของตัวระบุไฟล์ที่อยู่ในnative_handle_t
ที่โอบห่อโดยออบเจ็กต์นั้น กระบวนการต้องปิดตัวระบุไฟล์เหล่านี้เมื่อดำเนินการเสร็จแล้ว - การขนส่งที่รับ
hidl_handle
เป็นเจ้าของตัวระบุไฟล์ภายในnative_handle_t
ที่โอบห่อโดยออบเจ็กต์ ผู้รับสามารถใช้ตัวระบุไฟล์เหล่านี้ได้ตามเดิมในระหว่างการเรียกกลับธุรกรรม แต่ต้องโคลนแฮนเดิลเนทีฟเพื่อใช้ตัวระบุไฟล์หลังการเรียกกลับ การรับส่งจะเรียกใช้close()
สำหรับตัวระบุไฟล์โดยอัตโนมัติเมื่อธุรกรรมเสร็จสมบูรณ์
HIDL ไม่รองรับแฮนเดิลใน Java (เนื่องจาก Java ไม่รองรับแฮนเดิลเลย)
อาร์เรย์ที่มีขนาด
สำหรับอาร์เรย์ที่มีขนาดในโครงสร้าง HIDL องค์ประกอบของอาร์เรย์จะเป็นประเภทใดก็ได้ที่โครงสร้างมีได้ ดังนี้
struct foo { uint32_t[3] x; // array is contained in foo };
เครื่องสาย
สตริงจะปรากฏแตกต่างกันใน C++ และ Java แต่ประเภทพื้นที่เก็บข้อมูลการรับส่งข้อมูลพื้นฐานคือโครงสร้าง C++ โปรดดูรายละเอียดที่ประเภทข้อมูล C++ ของ HIDL หรือประเภทข้อมูล Java ของ HIDL
หมายเหตุ: การส่งสตริงไปยังหรือจาก Java ผ่านอินเทอร์เฟซ HIDL (รวมถึง Java ไปยัง Java) จะทำให้เกิดการแปลงชุดอักขระที่อาจไม่เก็บการเข้ารหัสเดิมไว้
เทมเพลตประเภท vec<T>
เทมเพลต vec<T>
แสดงบัฟเฟอร์ขนาดแปรผันที่มีอินสแตนซ์ของ T
T
อาจเป็นค่าใดค่าหนึ่งต่อไปนี้
- ประเภทพื้นฐาน (เช่น uint32_t)
- เครื่องสาย
- นิพจน์ที่ผู้ใช้กำหนด
- โครงสร้างที่ผู้ใช้กำหนด
- อินเทอร์เฟซ หรือคีย์เวิร์ด
interface
(รองรับvec<IFoo>
,vec<interface>
เท่านั้นในฐานะพารามิเตอร์ระดับบนสุด) - แฮนเดิล
- bitfield<U>
- vec<U> โดยที่ U อยู่ในรายการนี้ยกเว้นอินเทอร์เฟซ (เช่น ระบบไม่รองรับ
vec<vec<IFoo>>
) - U[] (อาร์เรย์ขนาดของ U) โดยที่ U อยู่ในรายการนี้ยกเว้นอินเทอร์เฟซ
ประเภทที่ผู้ใช้กําหนด
ส่วนนี้จะอธิบายประเภทที่ผู้ใช้กำหนด
Enum
HIDL ไม่รองรับลิสต์แบบไม่ระบุตัวตน มิเช่นนั้น อาร์เรย์ค่าคงที่ใน HIDL จะคล้ายกับ C++11 ดังนี้
enum name : type { enumerator , enumerator = constexpr , … }
Enumeration พื้นฐานจะกำหนดตามประเภทจำนวนเต็มอย่างใดอย่างหนึ่งใน HIDL หากไม่ได้ระบุค่าสำหรับตัวนับรายการแรกของ enum ตามประเภทจำนวนเต็ม ค่าเริ่มต้นจะเป็น 0 หากไม่ได้ระบุค่าสำหรับตัวนับที่ตามมา ค่าเริ่มต้นจะเป็นค่าก่อนหน้าบวก 1 เช่น
// RED == 0 // BLUE == 4 (GREEN + 1) enum Color : uint32_t { RED, GREEN = 3, BLUE }
นอกจากนี้ ยังเป็นได้ทั้งที่รับค่ามาจาก Enum ที่กําหนดไว้ก่อนหน้านี้ หากไม่ได้ระบุค่าสำหรับตัวนับรายการแรกของเอนทิตีย่อย (ในกรณีนี้คือ FullSpectrumColor
) ค่าเริ่มต้นจะเป็นค่าของตัวนับรายการสุดท้ายของเอนทิตีหลักบวก 1 เช่น
// ULTRAVIOLET == 5 (Color:BLUE + 1) enum FullSpectrumColor : Color { ULTRAVIOLET }
คำเตือน: การสืบทอด Enum จะทำงานย้อนกลับจากประเภทการสืบทอดอื่นๆ ส่วนใหญ่ คุณไม่สามารถใช้ค่า Enum ย่อยเป็นค่า Enum หลัก เนื่องจาก Enum ย่อยมีค่ามากกว่า Enum หลัก อย่างไรก็ตาม คุณสามารถใช้ค่า Enum หลักเป็นค่า Enum ย่อยได้อย่างปลอดภัยเนื่องจากค่า Enum ย่อยคือชุดที่รวมค่า Enum หลักทั้งหมด โปรดคำนึงถึงเรื่องนี้เมื่อออกแบบอินเทอร์เฟซ เนื่องจากประเภทที่อ้างอิงถึงลิสต์ค่าคงที่หลักจะอ้างอิงถึงลิสต์ค่าคงที่ย่อยในอินเทอร์เฟซรุ่นถัดไปไม่ได้
ค่าของ enum จะอ้างอิงด้วยไวยากรณ์โคลอน (ไม่ใช่ไวยากรณ์จุดสำหรับประเภทที่ฝัง) ไวยากรณ์คือ Type:VALUE_NAME
ไม่จำเป็นต้องระบุประเภทหากมีการอ้างอิงค่าในประเภท Enum หรือประเภทย่อยเดียวกัน ตัวอย่าง
enum Grayscale : uint32_t { BLACK = 0, WHITE = BLACK + 1 }; enum Color : Grayscale { RED = WHITE + 1 }; enum Unrelated : uint32_t { FOO = Color:RED + 1 };
ตั้งแต่ Android 10 เป็นต้นไป อาร์เรย์แบบจำกัดจะมีแอตทริบิวต์ len
ที่ใช้ได้ในนิพจน์คงที่
MyEnum::len
คือจํานวนรายการทั้งหมดในการแจกแจงนั้น
ซึ่งแตกต่างจากจํานวนค่าทั้งหมดที่อาจน้อยกว่าเมื่อมีค่าที่ซ้ำกัน
โครงสร้าง
HIDL ไม่รองรับโครงสร้างแบบไม่ระบุตัวตน ส่วนสตรูคเจอร์ใน HIDL จะคล้ายกับ C มาก
HIDL ไม่รองรับโครงสร้างข้อมูลที่มีขนาดแปรผันซึ่งอยู่ภายในสตริงทั้งหมด ซึ่งรวมถึงอาร์เรย์ที่มีความยาวไม่แน่นอนซึ่งบางครั้งใช้เป็นช่องสุดท้ายของโครงสร้างใน C/C++ (บางครั้งมีขนาดใหญ่เป็น [0]
) HIDL vec<T>
แสดงอาร์เรย์ที่มีขนาดแบบไดนามิกซึ่งมีข้อมูลที่จัดเก็บไว้ในบัฟเฟอร์แยกต่างหาก โดยอินสแตนซ์ดังกล่าวจะแสดงด้วยอินสแตนซ์ของ vec<T>
ใน struct
ในทำนองเดียวกัน string
สามารถอยู่ใน struct
ได้ (บัฟเฟอร์ที่เชื่อมโยงจะแยกกัน) ใน C++ ที่สร้างขึ้น อินสแตนซ์ของประเภทตัวแฮนเดิล HIDL จะแสดงผ่านพอยน์เตอร์ไปยังตัวแฮนเดิลเนทีฟจริง เนื่องจากอินสแตนซ์ของประเภทข้อมูลพื้นฐานมีความยาวแปรผัน
Union
HIDL ไม่รองรับยูเนียนที่ไม่ระบุตัวตน มิฉะนั้น สหภาพจะคล้ายกับ C
ยูเนียนต้องไม่มีประเภทการแก้ไข (เช่น ตัวชี้ ตัวระบุไฟล์ ออบเจ็กต์ Binder) โดยไม่จำเป็นต้องมีฟิลด์พิเศษหรือประเภทที่เชื่อมโยง และคัดลอกได้ง่ายๆ โดยใช้ memcpy()
หรือเทียบเท่า ยูเนี่ยนอาจไม่มี (หรือมีโดยใช้โครงสร้างข้อมูลอื่นๆ) ข้อมูลใดๆ ที่ต้องตั้งค่าออฟเซตของ Binder (กล่าวคือ แฮนเดิลหรือการอ้างอิงอินเทอร์เฟซ Binder) โดยตรง เช่น
union UnionType { uint32_t a; // vec<uint32_t> r; // Error: can't contain a vec<T> uint8_t b;1 }; fun8(UnionType info); // Legal
นอกจากนี้ คุณยังประกาศยูเนียนภายในโครงสร้างได้อีกด้วย เช่น
struct MyStruct { union MyUnion { uint32_t a; uint8_t b; }; // declares type but not member union MyUnion2 { uint32_t a; uint8_t b; } data; // declares type but not member }