我正在尝试在Rust中为现有的C项目编写一个插件模块。我一直在根据需要为C项目编写Rust绑定,而无论如何尝试与之交互,我的最新绑定每次都抛出一个段错误。
这是我绑定到的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绑定和调用:
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;
铁锈:
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;
};
铁锈:
#[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
}
}
}
答案 0 :(得分:2)
pub type switch_xml_t = switch_xml;
不等同于
typedef struct switch_xml *switch_xml_t;
此typedef隐藏一个指针。我真的不推荐这种样式-原因之一就是这个问题的存在。
锈面应为:
#[allow(non_camel_case_types)]
pub type switch_xml_t = *mut switch_xml;