2017-04-11 55 views
3

這是我想在C代碼做什麼:如何在使用Rust FFI時初始化一個不透明的C結構?

#include <some_lib.h> 
int main() { 
    some_lib_struct_t x; 
    some_lib_func(&x); 
} 

如何利用魯斯特庫的?下面是我到目前爲止有:

extern crate libc; 

struct some_lib_struct_t; 
#[link(name="some_lib")] 
extern { 
    fn some_lib_func(x: *mut some_lib_struct_t); 
} 

fn main() { 
    let mut x: some_lib_struct_t; 
    unsafe { 
     some_lib_func(&mut x); 
    } 
} 

當編譯我(不那麼令人驚訝的)得到的錯誤:use of possibly uninitialized `x`

編輯

閱讀Shepmaster的回答後,我看了看在庫的頭越來越近。正如他們所說,some_lib_struct_t只是一個指向actual_lib_struct_t的指針。我做了以下更改:

extern crate libc; 

struct actual_lib_struct_t; 
type some_lib_type_t = *mut actual_lib_struct_t; 

#[link(name="some_lib")] 
extern { 
    fn some_lib_func(x: *mut some_lib_type_t); 
} 

fn main() { 
    let mut x: some_lib_type_t; 
    unsafe { 
     x = std::mem::uninitialized(); 
     some_lib_func(&mut x); 
    } 
} 

它的工作原理!但是,我收到警告found zero-size struct in foreign module, consider adding a member to this struct, #[warn(improper_ctypes)] on by default。這是我能壓制的東西嗎?還是我需要改變某些東西?

回答

5

最安全的答案是自己初始化結構:

let mut x: some_lib_struct_t = some_lib_struct_t; 
unsafe { 
    some_lib_func(&mut x); 
} 

最接近模擬的C代碼是用mem::uninitialized

unsafe { 
    let mut x: some_lib_struct_t = std::mem::uninitialized(); 
    some_lib_func(&mut x); 
} 

必須確保some_lib_func完全初始化結構的所有成員,否則不安全將泄漏到unsafe塊之外。說到「struct的成員」,我幾乎可以保證你的代碼不會做你想要的。您已將some_lib_struct_t定義爲零大小。這意味着不會爲它分配堆棧空間,並且對它的引用不會是您的C代碼所期望的。

您需要鏡像Rust中C結構的定義,以便可以分配適當的大小,填充和對齊方式。通常,這意味着使用repr(C)

很多時候,C庫避免通過指針總是返回不透明類型暴露其內部結構表示:

+0

我得到它的工作使用MEM ::未初始化()。但是我收到了編譯器的警告。我用更多的信息更新了這個問題。 – EFTH

+0

@EFTH我已經解決了這個問題。看到我的答案中關於「零尺寸」的部分。如果你有一個*不透明的指針*,那麼請看3個鏈接的問題。 – Shepmaster