rust - 取消引用从 Rust 传递给 C 的类型定义指针时的段错误

标签 rust segmentation-fault ffi

我正在尝试用 Rust 为现有的 C 项目编写一个插件模块。我一直在为 C 项目编写 Rust 绑定(bind),因为我需要它们,而我最新的绑定(bind)每次都会抛出段错误,无论我如何尝试与之交互。

这是我要绑定(bind)的 C 函数签名:

switch_xml_t switch_xml_open_cfg(const char *file_path, switch_xml_t *node, switch_event_t *params) 
{
    switch_xml_t xml = NULL, cfg = NULL;
    *node = NULL; // <-- seg-fault happens here
    assert(MAIN_XML_ROOT != NULL);

    if (switch_xml_locate("configuration", "configuration", "name", file_path, &xml, &cfg, params, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
        *node = cfg;
    }
    return xml;
}

这是 Rust 绑定(bind)和调用:

extern "C" {
    pub fn switch_xml_open_cfg(
        file_path: *const c_char,
        node: *mut switch_xml_t,
        params: *mut switch_event_t,
    ) -> switch_xml_t;
} 
let mut cfg = switch_xml_t::default();
unsafe {
    libfreeswitch_sys::switch_xml_open_cfg(c_str!("skeleton_rust_raw.conf"), &mut cfg, std::ptr::null_mut());
}

我试过将结构传递给 C:

  • &mut cfg
  • Box::into_raw 指针
  • &mut cfg as *mut
  • 带有 mem::forget 以防万一。

我完全不知道我传入的指针在取消引用时如何以 null 结尾。

switch_xml_t 是一个类型别名:

C:

typedef struct switch_xml *switch_xml_t;

使用rust :

pub type switch_xml_t = switch_xml;

对于以下结构:

C:

struct switch_xml {
    /*! tag name */
    char *name;
    /*! tag attributes { name, value, name, value, ... NULL } */
    char **attr;
    /*! tag character content, empty string if none */
    char *txt;
    /*! path to free on destroy */
    char *free_path;
    /*! tag offset from start of parent tag character content */
    switch_size_t off;
    /*! next tag with same name in this section at this depth */
    switch_xml_t next;
    /*! next tag with different name in same section and depth */
    switch_xml_t sibling;
    /*! next tag, same section and depth, in original order */
    switch_xml_t ordered;
    /*! head of sub tag list, NULL if none */
    switch_xml_t child;
    /*! parent tag, NULL if current tag is root tag */
    switch_xml_t parent;
    /*! flags */
    uint32_t flags;
    /*! is_switch_xml_root bool */
    switch_bool_t is_switch_xml_root_t;
    uint32_t refs;
};

使用rust :

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct switch_xml {
    pub name: *mut c_char,
    pub attr: *mut *mut c_char,
    pub txt: *mut c_char,
    pub free_path: *mut c_char,
    pub off: switch_size_t,
    pub next: *mut switch_xml_t,
    pub sibling: *mut switch_xml_t,
    pub ordered: *mut switch_xml_t,
    pub child: *mut switch_xml_t,
    pub parent: *mut switch_xml_t,
    pub flags: u32,
    pub is_switch_xml_root_t: switch_bool_t,
    pub refs: u32,
}

Rust 定义还实现了 Default:

impl Default for switch_xml {
    fn default() -> Self {
        switch_xml {
            name: std::ptr::null_mut(),
            attr: std::ptr::null_mut(),
            txt: std::ptr::null_mut(),
            free_path: std::ptr::null_mut(),
            off: 0,
            next: std::ptr::null_mut(),
            sibling: std::ptr::null_mut(),
            ordered: std::ptr::null_mut(),
            child: std::ptr::null_mut(),
            parent: std::ptr::null_mut(),
            flags: 0,
            is_switch_xml_root_t: switch_bool_t::SWITCH_FALSE,
            refs: 0
        }
    }
}

最佳答案

pub type switch_xml_t = switch_xml;

不等同于

typedef struct switch_xml *switch_xml_t;

这个 typedef 隐藏了一个指针。我真的不推荐这种风格 - 一个原因就是为什么存在这个问题。

Rust 方面应该是:

#[allow(non_camel_case_types)]
pub type switch_xml_t = *mut switch_xml;

关于rust - 取消引用从 Rust 传递给 C 的类型定义指针时的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55443152/

相关文章:

compiler-errors - 使用 AtomicUsize::new 时,const fns 是一个不稳定的特性

rust - 我如何实现一种方法来处理 &str、Box<str>、Rc<str> 等?

rust - 派生 PartialEq 时无法移出包含盒装特征对象的枚举的借用内容

android - 使用 facebook android sdk 应用程序崩溃 API 4 登录

python - 访问 C 初始化的 ctypes 结构元素时出现段错误

rust - 正确拆分时,Rust不允许可变借用

c - 无法调试导致 shell 出现段错误的 .so 库

c - 显然我正在破坏堆栈——但是如何呢?

Lua/Luajit : Indexing and named method at the same time?

Haskell FFI - C 结构数组数据字段