2013-05-13 21 views
6

Tôi đang chuyển đổi một System.Action được quản lý thành một hàm std :: không được quản lý bên trong một dự án C++/CLI; nên tôi phát hành IntPtr nhất định sau khi sử dụng gọi lại, hoặc là nó không cần thiết?Nguyên soái :: GetFunctionPointerForDelegate: tôi có nên phát hành kết quả của nó không?

void MyClass::Execute(System::Action^ callback) 
{   

    IntPtr callbackPtr = Marshal::GetFunctionPointerForDelegate(callback); 
    std::function<void (void)> nativeCallback = static_cast<void (__stdcall *) (void)>(callbackPtr.ToPointer()); 

    m_nativeObject->Execute(wrappedCallback); 

    // should I release callbackPtr here? 
} 

Trả lời

6

Không. Không có phương thức lớp Marshal để thực hiện việc này. Giống như tất cả các mã được tạo động, đoạn thunk được tạo bởi phương thức này được liên kết với AppDomain và được tải xuống khi AppDomain được tải xuống.

Lưu ý rằng đây không phải là trường hợp đối tượng đại biểu, nó phải tuân thủ các quy tắc thu gom rác bình thường. Và bạn phải cẩn thận, thunk không không giữ cho nó còn sống. Đó là một lỗi trong mã của bạn, đại biểu có thể được thu thập trong khi mã gốc đang bận thực hiện. Bạn sẽ cần phải thêm dòng mã này vào cuối phương thức:

GC::KeepAlive(callback); 

Với giả định rằng gọi lại sẽ chỉ được thực hiện miễn là phương thức Execute() đang thực thi. Nếu mã không được quản lý lưu trữ con trỏ hàm ngoài cuộc gọi phương thức này thì bạn phải lưu trữ đối tượng ủy nhiệm ở đâu đó để giữ cho nó hợp lệ.

+0

ngay cả khi m_nativeObject-> Execute (wrapCallback) là đồng bộ? – Notoriousxl

+5

Một chủ đề sẽ làm hỏng ngày của bạn. Vâng, tuần. –

2

Bạn sẽ không cần nhả con trỏ. Bạn đã có con trỏ đến hàm (đó là kích thước 32/64 bit tùy thuộc vào kiến ​​trúc máy của bạn). Nếu cơ sở hạ tầng khung .net cần một cái gì đó nhiều hơn để chạy con trỏ nó sẽ giống nhau cho tất cả các phương thức để nó sẽ được phân bổ tĩnh (không có trạng thái).