相关疑难解决方法(0)

如何将Rust闭包转换为C风格的回调?

我正在尝试为一块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)

closures ffi rust

19
推荐指数
3
解决办法
4287
查看次数

如何创建Rust回调函数以传递给FFI函数?

这就是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上面的防锈绑定中的参数?

ffi rust

8
推荐指数
1
解决办法
2755
查看次数

将安全的 Rust 函数指针传递给 C

我已经创建了到 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)

ffi rust libpd

6
推荐指数
1
解决办法
3059
查看次数

将 Rust trait 传递给 C

我正在构建一个需要使用 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 ffi rust

5
推荐指数
1
解决办法
1153
查看次数

Rust FFI 将 trait 对象作为上下文来调用回调

好的,我正在努力实现以下目标:

  1. C调用生锈
  2. rust 回调 c 并在用户定义的 trait 对象上注册回调
  3. c 使用上下文调用 Rust
  4. Rust 调用上下文(trait 对象)上的回调

我一直在玩它。我走了很远,但还没有到那里。

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)

c ffi rust

5
推荐指数
1
解决办法
2082
查看次数

如何在 Rust 中正确包装 C 函数指针?

我有一个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 rust rust-bindgen

5
推荐指数
1
解决办法
2206
查看次数

是否有通用的Rust指针类型可以存储任何其他类型的指针,类似于C的void *?

我想为我的板条箱创建一个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 *),因为那样就不可能拥有存储位置的真实地址。

pointers rust

1
推荐指数
1
解决办法
130
查看次数

标签 统计

rust ×7

ffi ×6

c ×3

closures ×1

libpd ×1

pointers ×1

rust-bindgen ×1