【问题标题】:Rust static function fn pointer, which value to initialize?Rust 静态函数 fn 指针,初始化哪个值?
【发布时间】:2020-05-11 02:56:32
【问题描述】:

我正在尝试创建一个可从 C 调用的 Rust 库:

use std::os::raw::{c_int};

type OnDataCallback = unsafe extern "C" fn(data: *mut u8, len: usize) -> c_int;

static mut onDataCallback_: OnDataCallback = std::ptr::null();

#[no_mangle]
pub extern "C" fn registerOnDataCallback(
    data: *const u8, len: usize,
    cb: Option<OnDataCallback>) -> c_int
{
    onDataCallback_ = cb.unwrap();
    return 0;
}

#[no_mangle]
pub extern "C" fn doSomething()
{
    unsafe{onDataCallback_(mut "hello world" , 100)};
}

但我得到了:

--> interface.rs:5:46
  |
5 | static mut onDataCallback_: OnDataCallback = std::ptr::null();
  |                                              ^^^^^^^^^^^^^^^^ expected fn pointer, found *-ptr
  |
  = note: expected fn pointer `unsafe extern "C" fn(*mut u8, usize) -> i32`
            found raw pointer `*const _`

我不知道该放什么作为初始值。我不能让它没有一个,我不能放空。我应该放什么?

PS:如果我正在做的是一种不好的做法,请给我一个好的做法。我是 Rust 的新手。

【问题讨论】:

标签: c rust


【解决方案1】:

您应该将其包装在 Option 中并使用 None 对其进行初始化。

static mut onDataCallback_: Option<OnDataCallback> = None;

【讨论】:

  • 谢谢。这是最好的方法吗?我不得不把 unsafe:unsafe{onDataCallback_ = cb;} 否则它不会工作。
  • static mut 几乎从来都不是最好的方法。 Cell 包裹在 thread_local! 或 Mutex 包裹在 lazy_static 中(取决于您是否需要线程安全)几乎总是更好。
【解决方案2】:

你可以用一个 panic 的函数来初始化它:

static mut ON_DATA_CALLBACK: OnDataCallback = init;

extern "C" fn init(_: *mut u8, _: usize) -> c_int {
    panic!("Function pointer not initialized");
}

请注意static mut 是相当不安全的,通常不鼓励使用它,因为正确使用它非常困难。一个安全的替代方法是在 static 中使用 RefCell Mutex。由于Mutex 具有内部可变性,因此static 不需要是可变的。

更好的解决方案是在第一次调用doSomething() 时使用once_cell 或lazy_static 来初始化函数。

顺便说一句,Rust 字符串文字总是不可变。您可以通过分配String 来获取可变字符串。见this playground。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-24
    • 2017-08-26
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多