我正在尝试为一块C API编写一个Rusty包装器.我挣扎着一个C构造:
typedef bool (*listener_t) (int, int);
bool do_it(int x1, int y1, int x2, int y2, listener_t listener)
Run Code Online (Sandbox Code Playgroud)
除非侦听器返回false,否则该函数对一系列数字起作用.在那种情况下,它会中止计算.我想要一个像这样的Rust包装器:
fn do_with_callback<F>(start: (i32, i32), end: (i32, i32), callback: F)
where F: Fn(i32, i32) -> bool
Run Code Online (Sandbox Code Playgroud)
rust-bindgen 为我创建了这个,为了清晰起见略微编辑:
pub type listener_t = Option<extern "C" fn(x: c_int, y: c_int) -> c_bool>;
pub fn TCOD_line(xFrom: c_int, yFrom: c_int,
xTo: c_int, yTo: c_int,
listener: listener_t) -> c_bool;
Run Code Online (Sandbox Code Playgroud)
我应该如何在我的do_with函数中将闭包或特征引用转换为C风格的回调:
pub fn do_with_callback<F>(start: (i32, i32), end: (i32, i32), callback: F) -> Self
where F: Fn(i32, …Run Code Online (Sandbox Code Playgroud) 这就是C API的外观
void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int));
Run Code Online (Sandbox Code Playgroud)
rust-bindgen 为我生成了这个
pub fn mosquitto_connect_callback_set(
mosq: *mut Struct_mosquitto,
on_connect: ::std::option::Option<
extern "C" fn(
arg1: *mut Struct_mosquitto,
arg2: *mut ::libc::c_void,
arg3: ::libc::c_int,
) -> (),
>,
)
Run Code Online (Sandbox Code Playgroud)
如何创建一个生锈回调函数以传递给on_connect上面的防锈绑定中的参数?
我已经创建了到 C 库的 Rust 绑定,目前正在围绕它编写安全包装器。
问题是关于接受 C 函数指针的 C 函数,而这些指针无法接受任何自定义用户数据。
用一个例子来解释更容易,
C 库:
// The function pointer I need to pass,
typedef void (*t_function_pointer_library_wants)(const char *argument);
// The function which I need to pass the function pointer to,
void register_hook(const t_function_pointer_library_wants hook);
Run Code Online (Sandbox Code Playgroud)
绑定:
// For the function pointer type
pub type t_function_pointer_library_wants = ::std::option::Option<unsafe extern "C" fn(argument: *const ::std::os::raw::c_char)>;
// For the function which accepts the pointer
extern "C" {
pub fn register_hook(hook: t_function_pointer_library_wants);
}
Run Code Online (Sandbox Code Playgroud)
如果我可以像下面这样向用户公开 api,那就太好了,
// Let's assume …Run Code Online (Sandbox Code Playgroud) 我正在构建一个需要使用 Rust 对象调用一些 C 函数的 Rust 库。我有一个调用 C 函数的函数的特征,C 函数在 Rust 中定义如下:
extern {
fn process_trait(my_trait: MyTrait);
}
Run Code Online (Sandbox Code Playgroud)
这个想法是,用户可以为他的结构实现 trait,然后调用 C 函数(基本上,C 然后调用其他一些 Rust,它调用一些 Trait 函数)。这里的错误是:the trait core::marker::Sized is not implemented for the type Self,因为我正在传递*self给 process_trait。难道我做错了什么?我尝试稍微改变一下,即使是铸造,我得到这个错误或错误的类型。
我认为问题在于它应该是堆分配的,不是吗?我唯一要避免的是 API 看起来很丑。用户应该能够
struct MyUnit;
impl MyTrait for MyUnit...
MyUnit.callC();
Run Code Online (Sandbox Code Playgroud) 好的,我正在努力实现以下目标:
我一直在玩它。我走了很远,但还没有到那里。
C位:
#include <dlfcn.h>
#include <stdio.h>
void *global_ctx;
void c_function(void* ctx) {
printf("Called c_function\n");
global_ctx = ctx;
}
int main(void) {
void *thing = dlopen("thing/target/debug/libthing.dylib", RTLD_NOW | RTLD_GLOBAL);
if (!thing) {
printf("error: %s\n", dlerror());
return 1;
}
void (*rust_function)(void) = dlsym(thing, "rust_function");
void (*rust_cb)(void*) = dlsym(thing, "rust_cb");
printf("rust_function = %p\n", rust_function);
rust_function();
rust_cb(global_ctx);
}
Run Code Online (Sandbox Code Playgroud)
锈点:
extern crate libc;
pub trait Foo {
fn callback(&self);
}
extern …Run Code Online (Sandbox Code Playgroud) 我有一个Foo带有函数指针的 C 结构。在我的 Rust 绑定中,我希望允许用户设置此函数指针,但我希望避免用户必须处理 FFI 类型。
foo.h
struct Foo {
void* internal;
uint8_t a;
void (*cb_mutate_a)(void*);
};
struct Foo* foo_new();
void foo_free(struct Foo* foo);
void foo_call(struct Foo* foo);
Run Code Online (Sandbox Code Playgroud)
foo.c
struct Foo* foo_new() {
return calloc(1, sizeof(struct Foo));
}
void foo_free(struct Foo* foo) {
free(foo);
}
void foo_call(struct Foo* foo) {
return foo->cb_mutate_a(foo->internal);
}
Run Code Online (Sandbox Code Playgroud)
我当前的解决方案是创建一个 Rust 结构体Bar,它有一个指向 bindgen 生成的 C struct 的指针foo_sys::Foo,并且在其中我有一个特征对象 ( rust_cb),它是我想在 Rust API 中公开的实际回调。我将 C 设置cb为指向 awrapped_cb …
我想为我的板条箱创建一个C FFI API,但尚不清楚强制转换指针的安全性。伪代码:
#[no_mangle]
extern "C" fn f(...) -> *mut c_void {
let t: Box<T> = ...;
let p = Box::into_raw(t);
p as *mut c_void
}
Run Code Online (Sandbox Code Playgroud)
这可以按预期工作,但它的安全性如何?在C或C ++中,有一个特殊的void *指针,并且C ++标准声明可以强制转换为它。潜在地,sizeof(void *)可以是不相等的sizeof(T *),但有一个保证sizeof(void *)> = sizeof(T *)。
那Rust呢?是否有关于std::mem::size_of指针的保证或指针之间的安全转换?还是所有指针的实现大小相等,等于usize?
“通用”是指您可以转换X *而不会丢失任何东西。我不在乎类型信息;我关心的是指向不同事物的指针的大小不同,例如16位天中的near/ far指针。
4.10说
将“ pointer to cv T”转换为“ pointer to cv void”的结果指向类型为T的对象所在的存储位置的起点,
,这是不可能的sizeof(void *) < sizeof(T *),因为那样就不可能拥有存储位置的真实地址。