콜백 메서드로 대리자를 마샬링

이 샘플에서는 함수 포인터가 필요한 관리되지 않는 함수에 대리자를 전달하는 방법을 보여 줍니다. 대리자는 메서드에 대한 참조를 보유할 수 있는 클래스이고 형식이 안전한 함수 포인터나 콜백 함수에 해당합니다.

참고 항목

호출에서 대리자를 사용하면 공용 언어 런타임에서 대리자가 해당 호출 기간 동안 가비지 수집되지 않게 보호합니다. 그러나 관리되지 않는 함수에서 호출이 완료된 후 사용하기 위해 대리자를 저장하는 경우 관리되지 않는 함수가 대리자를 완료할 때까지 직접 가비지 수집이 수행되지 않게 처리해야 합니다. 자세한 내용은 HandleRef 샘플GCHandle 샘플을 참조하세요.

Callback 샘플에서는 원래 함수 선언과 함께 표시되는 다음과 같은 관리되지 않는 함수를 사용합니다.

  • TestCallBack - PinvokeLib.dll에서 내보냄

    void TestCallBack(FPTR pf, int value);
    
  • TestCallBack2 - PinvokeLib.dll에서 내보냄

    void TestCallBack2(FPTR2 pf2, char* value);
    

PinvokeLib.dll은 앞에 나열된 함수의 구현을 포함하는 관리되지 않는 사용자 지정 라이브러리입니다.

이 샘플에서 NativeMethods 클래스에는 TestCallBackTestCallBack2 메서드의 관리되는 프로토타입이 포함됩니다. 두 메서드 모두 대리자를 매개 변수로 콜백 함수에 전달합니다. 대리자의 시그니처는 대리자가 참조하는 메서드의 시그니처와 일치해야 합니다. 예를 들어 FPtrFPtr2 대리자는 DoSomethingDoSomething2 메서드에 동일한 시그니처가 있습니다.

프로토타입 선언

public delegate bool FPtr(int value);
public delegate bool FPtr2(String^ value);

private ref class NativeMethods
{
public:
    // Declares managed prototypes for unmanaged functions.
    [DllImport("..\\LIB\\PinvokeLib.dll")]
    static void TestCallBack(FPtr^ cb, int value);

    [DllImport("..\\LIB\\PinvokeLib.dll")]
    static void TestCallBack2(FPtr2^ cb2, String^ value);
};
public delegate bool FPtr(int value);
public delegate bool FPtr2(string value);

internal static class NativeMethods
{
    // Declares managed prototypes for unmanaged functions.
    [DllImport("..\\LIB\\PinvokeLib.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static extern void TestCallBack(FPtr cb, int value);

    [DllImport("..\\LIB\\PinvokeLib.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static extern void TestCallBack2(FPtr2 cb2, string value);
}

Public Delegate Function FPtr(ByVal value As Integer) As Boolean
Public Delegate Function FPtr2(ByVal value As String) As Boolean

Friend Class NativeMethods
    ' Declares managed prototypes for unmanaged functions.
    <DllImport("..\LIB\PinvokeLib.dll", CallingConvention:=CallingConvention.Cdecl)>
    Friend Shared Sub TestCallBack(
        ByVal cb As FPtr, ByVal value As Integer)
    End Sub

    <DllImport("..\LIB\PinvokeLib.dll", CallingConvention:=CallingConvention.Cdecl)>
    Friend Shared Sub TestCallBack2(
        ByVal cb2 As FPtr2, ByVal value As String)
    End Sub
End Class

함수 호출

public ref class App
{
public:
    static void Main()
    {
        FPtr^ cb = gcnew FPtr(&App::DoSomething);
        NativeMethods::TestCallBack(cb, 99);
        FPtr2^ cb2 = gcnew FPtr2(&App::DoSomething2);
        NativeMethods::TestCallBack2(cb2, "abc");
    }

    static bool DoSomething(int value)
    {
        Console::WriteLine("\nCallback called with param: {0}", value);
        // ...
        return true;
    }

    static bool DoSomething2(String^ value)
    {
        Console::WriteLine("\nCallback called with param: {0}", value);
        // ...
        return true;
    }
};
public class App
{
    public static void Main()
    {
        FPtr cb = new FPtr(App.DoSomething);
        NativeMethods.TestCallBack(cb, 99);
        FPtr2 cb2 = new FPtr2(App.DoSomething2);
        NativeMethods.TestCallBack2(cb2, "abc");
    }

    public static bool DoSomething(int value)
    {
        Console.WriteLine($"\nCallback called with param: {value}");
        // ...
        return true;
    }

    public static bool DoSomething2(string value)
    {
        Console.WriteLine($"\nCallback called with param: {value}");
        // ...
        return true;
    }
}
Public Class App
    Public Shared Sub Main()
        Dim cb As FPtr = AddressOf App.DoSomething
        Dim cb2 As FPtr2 = AddressOf App.DoSomething2
        NativeMethods.TestCallBack(cb, 99)
        NativeMethods.TestCallBack2(cb2, "abc")
    End Sub

    Public Shared Function DoSomething(ByVal value As Integer) As Boolean
        Console.WriteLine(ControlChars.CrLf + $"Callback called with param: {value}")
        ' ...
        Return True
    End Function

    Public Shared Function DoSomething2(ByVal value As String) As Boolean
        Console.WriteLine(ControlChars.CrLf + $"Callback called with param: {value}")
        ' ...
        Return True
    End Function
End Class

참고 항목