rust - 如何制作静态容器以从传递给 C 代码的回调中引用可变实例?
问题描述
对于我需要编写的库,我有一个表示用 C 编写的服务的结构:
struct RustService {
id: u8, /* it's me setting the id in the first place */
service: *mut c_void,
status: *mut c_void,
value: Option<u32>,
/* various fields here */
}
impl RustService {
fn new() -> /* can be wrapped*/RustService {
/* ... */
}
}
我有几个回调传递给 C 库,如下所示:
#[no_mangle]
extern "C" fn callback_handle(service: *mut c_void, size: *mut u32, buffer: *mut u8)
{
let id: u8 = c_library_get_id(service);
let instance: &mut RustService = /* get that from static container based on id */
if size = mem::size_of::<u32>() as u32 {
let value = buffer.cast::<u32>().read();
instance.value = Some(value);
} else {
panic!("Invalid length passed.");
}
}
我正在寻找的是一种经过验证的/良好的实践,可以在这里应用,不会导致死锁,我的回调可以使用 C 中的库引用正确的实例。C 中的那个库可以运行多个实例,但事实并非如此重要的。或者,我可以接受在这种情况下可以工作的单个实例模式。
其他方法RustService
需要调用例如具有以下签名的函数(来自 bindgen):
extern "C" pub fn clibCoreWork(status: *mut clibStatus, service: *mut clibService) -> u32;
并且该函数的核心可能会决定调用上面提到的这些回调。
即使在单线程中,内部互斥锁死锁,我采取的方法也让我大吃一惊:
lazy_static! {
static ref MY_INSTANCES: Mutex<HashMap<u8, Weak<Mutex<RustService>>>> = Mutex::new(HashMap::new());
}
我挖了互联网,但其他 Rustaceans 似乎没有发布任何关于此类问题的信息。
注意:我无法更改我正在使用的 C 库中的基础类型。在理想的世界中,它可以让我存储指向用户数据的指针,并且我会粗暴地将其转换为不安全代码中的可变引用。
解决方案
推荐阅读
- javascript - How to add a function to a function
- javascript - 我如何使用 json 作为变量
- node.js - 我的css样式没有出现,nodejs,express,hbs
- java - 使用 Java servlet 超过限制尝试登录
- mongodb - 传入的参数必须是12字节的单个String或24个十六进制字符的字符串,Mongoose ObjectId err
- python - 将列表中的项目传递给python中的sql查询
- python - 将多个数据框导出到多个工作簿
- r - 我将如何计算 R 中多个单元格之间的距离?
- snowflake-cloud-data-platform - - 从雪花中卸载数据 - 每行到一个单独的文件
- r - 并排散点图