Winapi 如何安全地表示动态大小的类型?

Winapi 如何安全地表示动态大小的类型?,winapi,rust,ffi,Winapi,Rust,Ffi,我正在一个使用动态大小类型的FFI库上编写一个安全包装器,我正在尝试确定在Rust中处理它们的最佳方法 特别是,我正在包装WindowsAPI的结构。它有一个字节(u8)表示当前版本,一个字节(u8)表示子权限的数量,六个字节([u8;6])表示标识符权限,然后是一系列表示子权限数量的DWORD(u32)。其拥有与次级机构数量相同的次级机构 通常,这种方法只通过WinAPI调用处理SID,所以我应该只有一个指向它的指针。此外,通过保持内部私有,我可以确保我的板条箱的消费者只能通过我控制的引用、B

我正在一个使用动态大小类型的FFI库上编写一个安全包装器,我正在尝试确定在Rust中处理它们的最佳方法

特别是,我正在包装WindowsAPI的结构。它有一个字节(
u8
)表示当前版本,一个字节(
u8
)表示子权限的数量,六个字节(
[u8;6]
)表示标识符权限,然后是一系列表示子权限数量的DWORD(
u32
)。其拥有与次级机构数量相同的次级机构

通常,这种方法只通过WinAPI调用处理SID,所以我应该只有一个指向它的指针。此外,通过保持内部私有,我可以确保我的板条箱的消费者只能通过我控制的引用、
Box
等访问它。但是,我确实需要声明某种类型的
Sid
类型,我正在尝试确定最佳方法

选项1:
winapi
板条箱只假设只有:

pub结构SID{
修订:字节,
SubAuthorityCount:字节,
IdentifierAuthority:SID\u IDENTIFIER\u AUTHORITY,//[u8;6]
次权限:[DWORD;1],
}
当您仅具有对它的引用时,这会起作用,但如果您创建了一个拥有的
Sid
,并将
SubAuthorityCount
设置为除1以外的任何值,WinAPI调用将读取无效的
SubAuthority
条目

选项2:优化分配最大数量的
DWORD
s:

pub结构SID{
修订:字节,
SubAuthorityCount:字节,
IdentifierAuthority:SID\u IDENTIFIER\u AUTHORITY,//[u8;6]
次权限:[DWORD;256],
}
这引入了内存开销(常见的情况是有几个子权限)。这还意味着WinAPI分配的SID不能仅强制转换为
SID
类型,因为Rust期望存在的附加
子权限
不是由SID分配的

选项3:动态调整大小的阵列:

pub结构SID{
修订:字节,
SubAuthorityCount:字节,
IdentifierAuthority:SID\u IDENTIFIER\u AUTHORITY,//[u8;6]
次权限:[DWORD],
}
现在它的大小不再是准确反映底层内存形状的大小。此外,由于不能直接声明
size
类型(我想?),因此只能使用FFI调用创建它。然而,现在所有指向它的指针都自动成为胖指针,这使得与FFI调用的互操作更加困难,因为FFI调用都需要裸(瘦)指针

选项4:它永远不会被分配,所以只要。。。没有什么。它将只作为引用处理,我将永远不会查看底层字段,因此根本没有理由公开任何内容:

pub结构SID{}
这感觉非常奇怪。我知道零大小类型在Rust中的行为与在C中的不同,在FFI调用中使用它们让我感到不舒服。但是,它确实反映了
SID
类型的使用方式:只能通过引用(或
Box
或其他指针)使用,并且字段不相关。但我肯定不能确定,例如,将ZST
&
s投射到原始指针并返回时的行为


或者别的什么?目前我正在使用选项1,将所有内容都保持私有,只是不直接访问任何字段(所有内容都是通过WinAPI调用),但我很好奇人们推荐哪种方法,以及我的分析是否正确。

我建议使用第三种方法,因为它是最正确表示语义的方法(当然,价格将在每个外国金融机构边界上明确确定)。但我担心这个问题主要是基于意见的。正如@Cerberus所说,这主要是一个意见问题。尽管如此,我还是选择选项4,这类似于C/C++在公共头中声明
struct SID;
,并在源代码或私有头中保留完整声明的方式。我相信问题由的答案回答。如果您不同意,请您的问题解释差异。否则,我们可以将此问题标记为已回答。
SID
不是动态大小类型,在C中无论如何都不存在此类型…我同意shep关于文档清楚说明的副本的观点“应用程序不应直接修改SID。若要创建和操作安全标识符,请使用“另请参阅”部分中列出的函数。”若要使其在Rust tooFWIW中不透明,则可能存在零子权限,则选项1将允许访问未定义的内存(错误)。如果子权限可能少于256个,则选项2将允许访问未定义的内存(错误)。具有尾随数组将无效,因为任何东西都无法按照Rust编译器的预期正确设置数组的长度(错误)。所有这些都可能触发未定义的行为。此处选择不透明结构是正确的。