C 字符串中缺少第一个字符

Missing first character from C string

我正在编写 girara 库的绑定,状态栏项目文本有问题:缺少第一个字符。

这是我绑定的一部分:

#[link(name="girara-gtk3")]
extern "C" {
    // Statusbar.
    pub fn girara_statusbar_item_add(session: *mut girara_session_t,
                                     expand: bool,
                                     fill: bool,
                                     left: bool,
                                     callback: girara_statusbar_event_t)
                                     -> *mut girara_statusbar_item_t;
    pub fn girara_statusbar_item_set_text(session: *mut girara_session_t,
                                          item: *mut girara_statusbar_item_t,
                                          text: *const c_char);
}

下面是我调用这些函数的方式:

let item = unsafe { girara_statusbar_item_add(session, true, true, true, None) };
assert!(item != 0 as *mut _);

let text = CString::new("girara-left").unwrap().as_ptr();
unsafe { girara_statusbar_item_set_text(session, item, text) };

但我没有显示 girara-left,而是只看到 irara-left

使用 CString 是将 *const c_char 发送到 FFI 的好方法吗?

为什么缺少第一个字符?

更新

这里发生了一些奇怪的事情。

如果我将代码更改为:

let text = CString::new("girara-left").unwrap().as_ptr();
let text2 = CString::new("hello World").unwrap();
unsafe { girara_statusbar_item_set_text(session, item, text) };

(其中text2未使用),显示文字hello World,没有意义。好像指针没有指向正确的地方

这个问题是因为 CString 在指针被发送到 ffi 函数之前被删除了(参见 here)。

解决方案是将 CString 绑定到一个变量:

let text = CString::new("girara-left").unwrap();
unsafe { girara_statusbar_item_set_text(session, item, text.as_ptr()) };