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

poi*_*idl 6 audio static rust

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

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

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

以下是介绍:

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

const LV2_Descriptor*
lv2_descriptor()
{
    return &descriptor;
}
Run Code Online (Sandbox Code Playgroud)

它返回一个指向STATICALLY分配的LV2_Descriptor类型结构的指针,

static const LV2_Descriptor descriptor = {
    AMP_URI,
    ...
};
Run Code Online (Sandbox Code Playgroud)

被定义为

typedef struct _LV2_Descriptor {
    const char * URI;
    ...
} LV2_Descriptor;
Run Code Online (Sandbox Code Playgroud)

为什么静态分配?在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
     }
Run Code Online (Sandbox Code Playgroud)

所以它没有静态分配,我永远不会释放它,我想为什么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, ...};
Run Code Online (Sandbox Code Playgroud)

但这不编译,有错误信息之类的

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();
Run Code Online (Sandbox Code Playgroud)

具体问题/问题:

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

oli*_*obk 4

简短的回答是,你现在还不需要。未来 Rust 可能会获得这种能力。

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

在这里,我认为这是解决以下事实的解决方法:无法将静态中的a 转换&[T]为 a 。*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
     }
}
Run Code Online (Sandbox Code Playgroud)