2015-11-06 67 views
1

作爲一個練習,我試圖在Rust中編寫一個GraphicsMagick FFI包裝器。我有一個問題複製一些參考的C代碼:GraphicsMagick FFI問題

Demo C code

Image 
    *image = (Image *) NULL; 
ImageInfo 
    *imageInfo; 
ExceptionInfo 
    exception; 

InitializeMagick(NULL); 
imageInfo=CloneImageInfo(0); 
GetExceptionInfo(&exception); 

這裏是我的(幼稚)翻譯防鏽:

let img: *mut ffi::Image; 
let img_info: *mut ffi::ImageInfo; 
let exception: *mut ffi::ExceptionInfo = ptr::null_mut(); 
unsafe {    
    ffi::InitializeMagick(ptr::null_mut()); 
    img_info = 
    ffi::CloneImageInfo(ptr::null_mut() as *const ffi::ImageInfo); 
    ffi::GetExceptionInfo(exception); 
    // ... 
} 

這編譯就好了,但是當我試圖運行它,我看到:

magick/error.c:388: GetExceptionInfo: Assertion `exception != (ExceptionInfo *) ((void *)0)' failed 

這是由引起的10。唯一的區別似乎是C異常沒有被「初始化」,但我不知道C是否知道null和空/未初始化指針之間是否有區別。

回答

4

C和鏽病代碼之間的區別是,C版在棧上分配一個實例ExceptionInfo並進入所述GetExceptionInfo一個指針引用該實例。

另一方面,您的Rust代碼會傳遞一個NULL指針。

GetExceptionInfo特別防範被傳遞NULL指針,你可以看到斷言的代碼here, in magick/error.c

我不知道你使用的是什麼類型的FFI綁定,但是如果ExceptionInfo在它們中被完全定義,那麼你應該能夠在堆棧上分配它,並且像在C版本中那樣傳遞它的引用:

let mut exception: ffi::ExceptionInfo = unsafe {std::mem::uninitialized()}; 
unsafe {ffi::GetExceptionInfo (&mut exception);} 
+0

完美,謝謝!我能夠使用這個逐字記錄。我沒有意識到'std :: mem :: uninitialized()',但這是我錯過了。也感謝鏈接相關的源代碼 - –

+0

不客氣! ) – ArtemGr

4

錯誤消息狀態(改寫了一下):

斷言exception != NULL失敗

也就是說,你不能 NULL傳遞給該方法。請注意C代碼:

ExceptionInfo exception; 

這是不是的指針。您需要爲它分配空間,然後傳遞對分配空間的引用。

documentation顯示了定義:

typedef struct _ExceptionInfo 
{ 
    char 
    *reason, 
    *description; 

    ExceptionType 
    severity; 

    unsigned long 
    signature; 
} ExceptionInfo; 

您需要在魯斯特表示這一點。類似這樣的未經測試的代碼:

extern crate libc; 

#[repr(C)] 
struct ExceptionInfo { 
    reason: *const libc::c_char, 
    description: *const libc::c_char, 
    severity: ExceptionType, 
    signature: libc::c_ulong, 
} 

#[repr(C)] 
enum ExceptionType { 
    UndefinedException, 
    WarningException = 300, 
    // the rest 
} 

然後你需要分配它並傳遞一個引用。更多未經測試的代碼:

let img_info; 
let mut exception = ffi::ExceptionInfo::new(); 

unsafe {    
    ffi::InitializeMagick(ptr::null_mut()); 
    img_info = 
     ffi::CloneImageInfo(ptr::null_mut() as *const ffi::ImageInfo); 
    ffi::GetExceptionInfo(&mut exception); 
    // ... 
} 

請注意,Rust風格是4個空格縮進。

+1

非常感謝您的解釋! –