带有C字符串的静态结构,用于lv2插件

时间:2015-07-10 06:56:09

标签: audio static rust

我正在尝试学习Rust(低级编程中的新手),并希望翻译一个小型的lv2放大器(音频)插件" amp.c" (C-code)从C到Rust。我实际上让它工作(here),但当主机终止时,valgrind说" 1个块中的64个字节肯定会丢失"。我想我知道为什么会这样,但我不知道如何解决它。

在你厌倦阅读之前,这是最后一个问题:

如何静态分配包含C字符串的结构?

以下是介绍:

为什么会发生(我认为): 主机加载库并调用lv2_descriptor()

const LV2_Descriptor*
lv2_descriptor()
{
    return &descriptor;
}

返回指向STATICALLY分配的类型为LV2_Descriptor的结构的指针,

static const LV2_Descriptor descriptor = {
    AMP_URI,
    ...
};

定义为

typedef struct _LV2_Descriptor {
    const char * URI;
    ...
} LV2_Descriptor;

为什么静态分配?在amp.c中它说:

  

最好静态定义描述符以避免泄漏内存   和非可移植的共享库构造函数和析构函数来清理   正确的。

但是,我将lv2_descriptor()翻译为Rust:

#[no_mangle]
pub extern fn lv2_descriptor(index:i32) -> *const LV2Descriptor {
     let s = "http://example.org/eg-amp_rust";
     let cstr = CString::new(s).unwrap();
     let ptr = cstr.as_ptr();
     mem::forget(cstr);

     let mybox = Box::new(LV2Descriptor{amp_uri: ptr}, ...);
     let bxptr = &*mybox as *const LV2Descriptor; 
     mem::forget(mybox);
     return  bxptr
     }

所以它没有静态分配,我永远不会释放它,我想为什么valgrind抱怨?

我该如何解决? 我试图在Rust中做同样的事情,就像C代码一样,即静态分配结构(在lv2_descriptor()之外)。目标是与lv2库完全兼容,即" ...以避免泄漏内存..."正如报价中所述,对吧?所以我尝试了类似的东西:

static ptr1: *const u8 = (b"example.org/eg-amp_rust\n\0").as_ptr();
static ptr2: *const libc::c_char = ptr1 as *const libc::c_char;
static desc: LV2Descriptor = LV2Descriptor{amp_uri: ptr2, ...};

但这不编译,有错误消息,如

src/lib.rs:184:26: 184:72 error: the trait `core::marker::Sync` is not implemented for the type `*const u8` [E0277]
src/lib.rs:184 static ptr1: *const u8 = b"http://example.org/eg-amp_rust\n\0".as_ptr();
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/lib.rs:184:26: 184:72 note: `*const u8` cannot be shared between threads safely
src/lib.rs:184 static ptr1: *const u8 = b"http://example.org/eg-amp_rust\n\0".as_ptr();
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/lib.rs:184:26: 184:72 error: static contains unimplemented expression type [E0019]
src/lib.rs:184 static ptr1: *const u8 = b"http://example.org/eg-amp_rust\n\0".as_ptr();

具体问题/问题:

如何静态分配包含C字符串的结构?

1 个答案:

答案 0 :(得分:4)

简短的回答是,你现在不是。 Future Rust可能会获得这种能力。

您可以做的是静态分配包含空指针的结构,并在调用函数时将这些空指针设置为有用的东西。 Rust有static mut。它需要不安全的代码不是线程安全,并且(据我所知)被视为代码异味

就在这里,我认为这是一个解决方法,因为无法在静态中将&[T]转换为*const T

static S: &'static [u8] = b"http://example.org/eg-amp_rust\n\0";
static mut desc: LV2Descriptor = LV2Descriptor {
    amp_uri: 0 as *const libc::c_char, // ptr::null() isn't const fn (yet)
};

#[no_mangle]
pub extern fn lv2_descriptor(index: i32) -> *const LV2Descriptor {
     let ptr = S.as_ptr() as *const libc::c_char;
     unsafe {
        desc.amp_uri = ptr;
        &desc as *const LV2Descriptor
     }
}