나는 C에서 몇 가지 기능을 가지고 있으며 이것을 .net 응용 프로그램에서 사용할 것입니다. 이를 위해 C++/cli로 Wrapper 클래스를 작성했습니다.C++/cli finalizer의 무료 GCHandle에 대한 유용한 정보
에서 c 인터페이스는 콜백 함수이며 이것을 .net 대리자로 묶었습니다.
그러나 콜백 gcHandle에 대한 관리되지 않는 소스를 어떻게 릴리스해야합니까? finalizer에서 IsAllocated와 Free를 GCHandle에서 호출 할 수 있습니까? 관리되는 ressource이고 gc가 이미 그것을 릴리스 할 수 있습니까? 여기
// 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_;
// ...
};
이 코드 안전하고이를 위해 가장 좋은 방법은 무엇인가 여기
이는 C 인터페이스를위한 코드?미리 감사드립니다.
빠른 응답을 보내 주셔서 감사합니다. 추가 질문이 설정됩니다. callbackDelegate_ = nullptr; finalizer에서 안전하고 필요한가? –
필드가 더 이상 사용되지 않도록 개체가 이미 참조로 남아 있지 않아서 필요하지 않습니다. 그냥 진술을 제거하십시오. –
재배치는 어떻게됩니까? 이 문서에서는 https://msdn.microsoft.com/en-us/library/367eeye0.aspx (두 번째 예 참조)에서 "대리인이 재배치되지 않도록하는 GCHandle의 전역 인스턴스"가 필요하다고 말합니다. MyWrapper 클래스의 객체가 처음으로 인스턴스화 된 후에 가비지 수집기가 관리 된 위임을 재배치 할 수 있습니까? – Tarc