다음을 통해 공유


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

이 샘플에서는 함수 포인터를 예상하는 관리되지 않는 함수에 대리자를 전달하는 방법을 보여 줍니다. 대리자는 메서드에 대한 참조를 보유할 수 있는 클래스이며 형식이 안전한 함수 포인터 또는 콜백 함수와 동일합니다.

비고

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

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

  • TestCallBack PinvokeLib.dll에서 내보낸.

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

    void TestCallBack2(FPTR2 pf2, char* value);
    

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

이 샘플에서 NativeMethods 클래스는 TestCallBackTestCallBack2 메서드에 대한 관리되는 프로토타입을 포함합니다. 두 메서드 모두 대리자를 콜백 함수에 매개 변수로 전달합니다. 대리자의 서명은 참조하는 메서드의 서명과 일치해야 합니다. 예를 들어, FPtr 대리자와 FPtr2 대리자는 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

참고하십시오