我想调用WSALookupServiceNext
,这是一个extern C
函数,具有简化的界面,如:
#[repr(C)]
pub struct Foo {
version: u32,
a: u32,
}
extern "C" {
pub fn get_foo(p: *mut Foo, nbytes: *mut u32) -> i32;
}
你给它指向Foo
结构和nbytes = ::std::mem::size_of::<Foo>()
的指针,如果一切正常,它会填充结构。
如果在编译程序后ABI发生变化,请执行以下操作:
#[repr(C)]
pub struct Foo {
version: u32,
a: u32,
b: f64,
}
然后该函数指示失败,nbytes
将包含Foo
的正确大小。我该如何处理这种情况?
在C或C ++中,我会简化我的生活并做:
union {
struct Foo foo;
char buf[4000];//should be enough for 10 years
} a;
uint32_t nbytes = sizeof(a);
if (get_foo(&a.foo, &nbytes) != 0) {
return -1;
}
这可能在Rust吗?如果没有,我应该如何分配大小&gt; size_of::<Foo>()
,但指针指向Foo
? Foo
由bindgen生成,因此我无法更改其声明并将字节添加到其末尾。
我正在使用Rust 1.15.1。
答案 0 :(得分:1)
您可以使用枚举(也称为标记联合),它已经为类型标记包含一些空间,并且访问内部值不太方便。 Nightly builds of Rust have untagged unions,但这还不稳定,阅读或借用它的字段需要不安全的代码。由于评论表明您可以手动分配。直接的方法是使用包含结构的结构,分配外部:
#[repr(C)]
pub struct Foo {
version: u32,
a: u32,
}
#[repr(C)]
pub struct FooPadded {
foo: Foo,
_reserved: [u8; 4000],
}
答案 1 :(得分:1)
每晚构建的Rust都有untagged unions,因此您可以使用与C / C ++相同的解决方法。
#![feature(untagged_unions)]
#[repr(C)]
pub struct Foo {
version: u32,
a: u32,
b: f64,
}
#[repr(C)]
union PaddedFoo {
foo: Foo,
_padding: [u8; 4000],
}
fn main() {
println!("{}", std::mem::size_of::<Foo>());
println!("{}", std::mem::size_of::<PaddedFoo>());
}