我需要使用来自 C++/CLI 的非托管 API。此 API 存储指向任意用户数据的 void 指针和一些回调。然后它最终调用这些回调,将用户数据作为 void* 传递。
到目前为止,我有一个本地类将其“this”指针作为用户数据传递,并使用该指针将 API 调用回该类,即:
static void __stdcall Callback(void* userData) {
((MyType*)userData)->Method();
}
class MyType {
public:
MyType() { RegisterWithApi((void*)this, Callback); }
void Method();
};
我正在尝试使用托管类来翻译它。我发现 gcroot 类型可用于在本机代码中安全地存储托管引用,所以这就是我现在的做法:
// This is called by the native API
static void __stdcall Callback(void* userData) {
// Cast back to gcroot and call into managed code
(*(gcroot<MyType^>*)userData)->Method();
}
ref class MyType {
gcroot<MyType^>* m_self;
public:
MyType() {
m_self = new gcroot<MyType^>;
RegisterWithApi((void*)m_self, Callback);
}
~MyType() { delete m_self; }
// Method we want called by the native API
void Method();
}
虽然这对 C++/CLI 编译器来说似乎很好,但我并不完全放心。据我了解,gcroot 以某种方式跟踪其托管引用,因为它被 GC 移动。当非托管代码存储为 void* 时,它会设法做到这一点吗?这段代码安全吗?
谢谢。