【发布时间】:2014-11-10 20:50:27
【问题描述】:
我正在尝试在 Rust 中创建一个动态库,将结构导出为符号,该符号将通过 dlopen() 加载到 C 程序中。
但是,我在访问结构中的第二个字符串时遇到了一些段错误,所以我做了一个小测试程序来尝试找出我做错了什么。
这是 Rust 代码 (test.rs),使用“rustc --crate-type dylib test.rs”编译:
#[repr(C)]
pub struct PluginDesc {
name: &'static str,
version: &'static str,
description: &'static str
}
#[no_mangle]
pub static PLUGIN_DESC: PluginDesc = PluginDesc {
name: "Test Plugin\0",
version: "1.0\0",
description: "Test Rust Plugin\0"
};
这是尝试加载库(test.c)的C程序,使用“gcc test.c -ldl -o test”编译:
#include <dlfcn.h>
#include <stdio.h>
typedef struct {
const char *name;
const char *version;
const char *description;
} plugin_desc;
int main(int argc, char **argv) {
void *handle;
plugin_desc *desc;
handle = dlopen("./libtest.so", RTLD_LOCAL | RTLD_LAZY);
if (!handle) {
printf("failed to dlopen: %s\n", dlerror());
return 1;
}
desc = (plugin_desc *) dlsym(handle, "PLUGIN_DESC");
if (!desc) {
printf("failed to dlsym: %s\n", dlerror());
return 1;
}
printf("name: %p\n", desc->name);
printf("version: %p\n", desc->version);
printf("description: %p\n", desc->description);
return 0;
}
这是输出:
name: 0x7fa59ef8d750
version: 0xc
description: 0x7fa59ef8d75c
可以看到,desc->version的地址其实是0xc(12),也就是第一个字符串的长度。所以看起来打包到库中的结构也包含内存地址后面的字符串长度。
我在这里使用了错误的字符串类型吗?如您所见,我还必须手动终止字符串 NULL。我尝试使用 CString 包装器,但在这种情况下似乎不起作用(“静态项不允许有析构函数”)。
我每晚在 Linux 上运行最新的 Rust:
$ rustc --version
rustc 0.12.0-pre-nightly (f8426e2e2 2014-09-16 02:26:01 +0000)
【问题讨论】:
-
您是否尝试过将
*i8指针放在结构中? -
看起来 rust-strings 不只是
char *的。是否有一个包含用于与 C 链接的 rust 字符串定义的 .h 文件?
标签: c string struct rust dlopen