gpt4 book ai didi

delegates - c++/cli 终结器中免费 GCHandle 的最佳实践

转载 作者:行者123 更新时间:2023-12-02 23:36:50 26 4
gpt4 key购买 nike

我在 c 中有一些函数,我会在 .net 应用程序中使用它。为此,我用 C++/cli 编写了一个包装器类。

C 接口(interface)中有一个回调函数,并将其包装在 .net 委托(delegate)中。

但是我应该如何释放回调gcHandle的非托管资源呢?是否允许在终结器中从 GCHandle 调用 IsAllocation 和 Free?因为它是托管资源,gc 是否可能已经释放它?

这是 C 接口(interface)的代码:

// C functions

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*my_native_callback)(const uint8_t buffer[], uint32_t buffer_len);

void register_callback(my_native_callback c, uint32_t* id);

void remove_callback(uint32_t id);

#ifdef __cplusplus
}
#endif

这是 .net 包装器:

// .net wrapper (c++/cli)
public ref class MyWrapper
{
public:
MyWrapper()
{
RegisterCallback();
}

// Destructor.
~MyWrapper()
{
this->!MyWrapper();
}

protected:
// Finalizer.
!MyWrapper()
{
RemoveCallback(); // <- Is this safe?
// ... release other unmanaged ressorces
}

private:
void RegisterCallback()
{
uint32_t id = 0;
callbackDelegate_ = gcnew MyCallbackDelegate(this, &MyWrapper::OnCallback);
callbackHandle_ = System::Runtime::InteropServices::GCHandle::Alloc(callbackDelegate_);
System::IntPtr delegatePointer = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(callbackDelegate_);
register_callback(static_cast<my_native_callback>(delegatePointer.ToPointer()), &id);
callbackId_ = id;
}

void RemoveCallback()
{
if (callbackId_)
{
remove_callback(callbackId_);
callbackId_ = 0;
}
if (callbackHandle_.IsAllocated) // It this safe in the finalizer?
{
callbackHandle_.Free(); // It this safe in the finalizer?
}
callbackDelegate_ = nullptr; // It this safe in the finalizer?
}


void OnCallback(const uint8_t* buffer, uint32_t buffer_len)
{
// ...
}

private:
[System::Runtime::InteropServices::UnmanagedFunctionPointer(System::Runtime::InteropServices::CallingConvention::Cdecl)]
delegate void MyCallbackDelegate(const uint8_t* buffer, uint32_t buffer_len);
MyCallbackDelegate^ callbackDelegate_;
System::Runtime::InteropServices::GCHandle callbackHandle_;
int callbackId_;
// ...
};

代码片段安全吗?最佳实践是什么?

提前谢谢您。

最佳答案

无需向委托(delegate)对象添加额外的 GCHandle 引用。您已经在callbackDelegate_字段中正确存储了一个引用,足以让垃圾收集器相信委托(delegate)正在使用中并且不应被收集。不需要额外的引用。

只需从代码中删除callbackHandle_即可。

关于delegates - c++/cli 终结器中免费 GCHandle 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15339608/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com