【问题标题】:GraphicsMagick FFI issueGraphicsMagick FFI 问题
【发布时间】:2015-11-06 22:54:30
【问题描述】:

作为一个练习,我正在尝试用 Rust 编写一个 GraphicsMagick FFI 包装器。我在复制一些参考 C 代码时遇到问题:

Demo C code:

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

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

这是我对 Rust 的(天真)翻译:

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

这是由ffi::GetExceptionInfo(exception) 引起的。唯一的区别似乎是 C 异常没有“初始化”,但我对 C 的了解还不够,无法知道 null 和空/未初始化的指针之间是否存在差异。

【问题讨论】:

    标签: rust ffi


    【解决方案1】:

    您的 C 代码和 Rust 代码之间的区别在于 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);}
    

    【讨论】:

    • 完美,谢谢!我能够逐字使用这个。我不知道std::mem::uninitialized(),但这是我所缺少的。也感谢链接相关的源代码--
    【解决方案2】:

    错误信息状态(改写了一下):

    断言exception != NULL 失败

    也就是说,您不能将 NULL 传递给该方法。注意 C 代码:

    ExceptionInfo exception;
    

    不是指针。您需要为其分配空间,然后传入对分配空间的引用。

    documentation 显示定义:

    typedef struct _ExceptionInfo
    {
      char
        *reason,
        *description;
    
      ExceptionType
        severity;
    
      unsigned long
        signature;
    } ExceptionInfo;
    

    你需要用 Rust 来表示它。像这样未经测试的代码:

    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 个空格缩进。

    【讨论】:

    • 非常感谢您的解释!
    猜你喜欢
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    相关资源
    最近更新 更多