此示例演示如何将委托传递给需要函数指针的非托管函数。 委托是可以容纳方法引用的类,等效于类型安全函数指针或回调函数。

注释

在调用内使用委托时,公共语言运行时防止在该调用的持续时间内对委托执行垃圾回收。 但是,如果非托管函数存储了该委托,以便在调用完成后使用,则必须手动防止垃圾回收,直到非托管函数结束对该委托的使用为止。 有关详细信息,请参阅 HandleRef 示例 和 GCHandle 示例。

回调示例使用以下非托管函数(与其原始函数声明一同显示):

TestCallBack 从 PinvokeLib.dll 导出。

void TestCallBack(FPTR pf, int value);

TestCallBack2 从 PinvokeLib.dll 导出。

void TestCallBack2(FPTR2 pf2, char* value);

PinvokeLib.dll 是一个自定义非托管库,其中包含以前列出的函数的实现。

在此示例中,NativeMethods类包含TestCallBack和TestCallBack2方法的托管原型。 这两种方法都以参数的形式将委托传递给回调函数。 委托的签名必须与它引用的方法的签名匹配。 例如,FPtr 和 FPtr2委托的签名与 DoSomething 和 DoSomething2 方法相同。

声明原型

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.

Friend Shared Sub TestCallBack(

ByVal cb As FPtr, ByVal value As Integer)

End Sub

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

另请参阅

其他封送处理示例

平台调用数据类型

在托管代码中创建原型