我正在包装一个 C API,它允许调用者通过函数调用设置/获取任意指针。通过这种方式,C API 允许调用者将任意数据与 C API 对象之一相关联。此数据不用于任何回调,它只是一个指针,用户可以将其隐藏起来并在以后获取。
我的包装器结构为包含此指针的 C 对象实现了 Drop 特性。我希望能够做的,但不确定是否可能,如果包装器结构下降时指针不为空,则正确下降数据。我不确定如何从原始 c_void 指针恢复正确的类型。
我想到的两个选择是
- 在包装器中实现这两个调用的行为。不要对 C API 进行任何调用。
- 不要尝试为这些函数提供任何类型的更安全的接口(interface)。记录指针必须由包装器的调用者管理。
我想做的事可行吗?如果没有,是否有针对此类情况的普遍接受的做法?
最佳答案
由于以下原因,天真 + 全自动方法是不可能的:
释放内存不会调用 drop/deconstructors/...:C API 可用于具有应正确解构的对象的语言,例如C++ 或 Rust 本身。因此,当您仅存储一个内存指针时,您不知道要调用正确的函数(您既不知道哪个函数也不知道调用约定是什么样的)。
which memory allocator?: 内存分配和释放不是一件小事。您的程序需要从操作系统请求内存,然后以智能方式管理这些资源,以提高效率和正确性。这通常由图书馆完成。在 Rust 的情况下,使用 jemalloc (但 can be changed )。因此,即使您要求 API 调用者仅传递 Plain Old Data (这应该更容易破坏)你仍然不知道调用哪个库函数来释放内存。仅使用
libc::free
是行不通的(它可以但可能会失败)。
解决方案:
dealloc 回调:您可以要求 API 用户设置一个额外的指针,比方说一个
void destruct(void* ptr)
函数。如果这个不为 NULL,则在放置期间调用该函数。您还可以使用int
作为返回类型,以在销毁出错时发出信号。在这种情况下,您可以例如panic!
。全局回调:假设您要求您的用户仅传递 POD(普通旧数据)。要知道调用内存分配器的哪个
free
函数,您可以请求用户注册一个全局void (*free)(void* ptr)
指针,该指针在降低。您也可以将其设为可选。
关于rust - 删除存储在 FFI 中的 Rust void 指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38289355/