C++/CLI Managed Function To Native Callback Function

3675 ワード

一.キーカーネル
System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate

この関数はDelegateからNative Functionへの変換を実現します.
二.具体的な手順1.Native Functionと一致するDelegate Native Functionを作成する:
typedef bool (*ONSESSRELY)(HANDLE_CONN, HANDLE_SESSION, long); //long   32bit

Managed Delegate:
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate bool ONSESSIONREPLY(IntPtr hConnect, IntPtr hSession, eAbossFn fnId);// eAbossFn   enum:int

注意呼び出し方法はNative Functionと一致する必要があります
  • Managed FunctionをDelegate
  • に変換
    ONSESSIONREPLY^ pFunc = gcnew ONSESSIONREPLY(this, &YourClass::MemberFunction);
    ONSESSIONREPLY^ pFunc = gcnew ONSESSIONREPLY(YourClass::StatiMemberFunction);
  • DelegateをNative Function
  • に変換
    GCHandle gch = GCHandle::Alloc(pFunc);// System::Runtime::InteropServices::GCHandleType::Pinned);   
    auto thunk = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(pFunc);
    ::Native_RegisterService(hSess.ToInt32(), thunk.ToPointer());
    //Free gch, after Native used thunk

    4.注意事項Delegateインスタンスについては、Nativeによって呼び出されるまでGCによって回収されない必要があります.2つの方法があります.a.クラスの構造に保存b.GCHandleに保存GCで回収されるとNativeがthunkを呼び出すと未知のコンテンツにアクセスするので、自分でクラス構造に保存したり、GCHandleに保存したりすることができます.どちらの方法も、Delegateのライフサイクルを自分で維持する必要があります.注意:DelegateはGCHandle::Allocを使用してDelegateを保存する場合、必要もなく、Pinnedに設定することもできません.GCHadle::AllocがDelegateを保存した後、Pinnedがないため、実際のアドレスはGCMoveになりますが、関数GetFunctionPointerForDelegateはDelegateをNative Functionに変換する際に、GCの外部に「native thunk」を作成します.この「native thunk」こそnativeアクセスのアドレスであり、もちろんnative thunk内部ではmanaged delegateにアクセスします.
    Chris Brumme wrote: Along the same lines, managed Delegates can be marshaled to unmanaged code, where they are exposed as unmanaged function pointers. Calls on those pointers will perform an unmanaged to managed transition; a change in calling convention; entry into the correct AppDomain; and any necessary argument marshaling. Clearly the unmanaged function pointer must refer to a fixed address. It would be a disaster if the GC were relocating that! This leads many applications to create a pinning handle for the delegate. This is completely unnecessary. The unmanaged function pointer actually refers to a native code stub that we dynamically generate to perform the transition & marshaling. This stub exists in fixed memory outside of the GC heap.
    ここにリンクの内容を書きます
    https://stackoverflow.com/questions/33393690/passing-a-c-sharp-callback-function-into-managed-and-unmanaged-c-libraries
    https://stackoverflow.com/questions/28982669/does-gchandle-alloc-allocate-memory