2015-11-06 27 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

非常感谢您的解释! –