GraphicsMagick FFI 问题
GraphicsMagick FFI issue
作为练习,我尝试用 Rust 编写 GraphicsMagick FFI 包装器。我在复制一些参考 C 代码时遇到问题:
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 异常不是 "initialized",但我对 C 的了解还不足以知道 null 和 empty/uninitialized 指针之间是否存在差异。
错误消息指出(重写了一点):
Assertion exception != NULL
failed
也就是说,您不能将 NULL 传递给该方法。注意C代码:
ExceptionInfo exception;
这是不是指针。您需要为其分配 space,然后传入对分配的 space.
的引用
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 space 个缩进。
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);}
作为练习,我尝试用 Rust 编写 GraphicsMagick FFI 包装器。我在复制一些参考 C 代码时遇到问题:
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 异常不是 "initialized",但我对 C 的了解还不足以知道 null 和 empty/uninitialized 指针之间是否存在差异。
错误消息指出(重写了一点):
Assertion
exception != NULL
failed
也就是说,您不能将 NULL 传递给该方法。注意C代码:
ExceptionInfo exception;
这是不是指针。您需要为其分配 space,然后传入对分配的 space.
的引用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 space 个缩进。
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);}