首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET Framework >

怎么在非托管C++中调用托管C#中的回调函数

2013-01-04 
如何在非托管C++中调用托管C#中的回调函数大家好,我刚刚接触.net,下面是msdn关于回调函数的解释http://msd

如何在非托管C++中调用托管C#中的回调函数
大家好,我刚刚接触.net,下面是msdn关于回调函数的解释
http://msdn.microsoft.com/zh-cn/library/843s5s5x(v=vs.100).aspx
问题是如何在非托管C++中调用托管C#中的回调函数,文章中没有说。
为了防止垃圾回收,我用HandleRef盯住了回调函数,当C#程序执行了
CallBack myCallBack = new CallBack(EnumReportApp.Report);
IntPtr ptr = Marshal.GetFunctionPointerForDelegate(myCallBack);
HandleRef hr = new HandleRef(myCallBack, ptr);
EnumWindows(hr, 0);
之后,myCallBack的指针被传递到了C++,假设指针的形参名是pCallBack,在C++的DLL中直接执行
pCallBack();
然后程序抛出了异常:“访问了受保护的内存区域”,继续运行抛出“回调函数被垃圾回收”。
我觉得应该是C++调用C#的函数指针的方法不对,请大家看看问题出在哪里?


[解决办法]
 全部折叠全部展开      代码:全部 代码:多个 代码:Visual Basic 代码:C# 代码:Visual C++ 代码:J# 代码:JScript  
Visual Basic
C#
Visual C++
J#
JScript
.NET Framework 开发人员指南 
Callback 示例 
请参见  发送反馈意见 
 

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

注意: 
当您在调用内部使用委托时,公共语言运行库将在该调用的持续时间内防止对委托执行垃圾回收。但是,如果非托管函数存储该委托以供在该调用完成后使用,则您必须手动防止进行垃圾回收,直到非托管函数完成对该委托的使用为止。有关更多信息,请参见 HandleRef 示例和 GCHandle 示例。
 

Callback 示例使用以下非托管函数(这里同时显示其原始函数声明): 

从 PinvokeLib.dll 导出的 TestCallBack。 

  复制代码 
void TestCallBack(FPTR pf, int value);
 

从 PinvokeLib.dll 导出的 TestCallBack2。 

  复制代码 
void TestCallBack2(FPTR2 pf2, char* value);
 

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

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

下面的代码示例的源代码由 .NET Framework 平台调用技术示例 提供。

声明原型
Visual Basic  复制代码 
Public Delegate Function FPtr( ByVal value As Integer ) As Boolean
Public Delegate Function FPtr2( ByVal value As String ) As Boolean

Public Class LibWrap
   ' Declares managed prototypes for unmanaged functions.
   Declare Sub TestCallBack Lib "..\LIB\PinvokeLib.dll" ( ByVal cb _
      As FPtr, ByVal value As Integer )
   Declare Sub TestCallBack2 Lib "..\LIB\PinvokeLib.dll" ( ByVal cb2 _
      As FPtr2, ByVal value As String )
End Class 'LibWrap

 
C#  复制代码 
public delegate bool FPtr( int value );
public delegate bool FPtr2( String value );

public class LibWrap
{// Declares managed prototypes for unmanaged functions.
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestCallBack( FPtr cb, int value );   
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestCallBack2( FPtr2 cb2, String value );   
}
 

调用函数
Visual Basic  复制代码 
Public Class App


   Public Shared Sub Main()

      Dim cb As FPtr
      cb = AddressOf App.DoSomething
      Dim cb2 As FPtr2
      cb2 = AddressOf App.DoSomething2
      LibWrap.TestCallBack( cb, 99 )
      LibWrap.TestCallBack2( cb2, "abc" )
   End Sub 'Main
   Public Shared Function DoSomething( ByVal value As Integer ) As Boolean
      Console.WriteLine( ControlChars.CrLf + "Callback called with _
         param: {0}", value )
      …
   End Function 'DoSomething
   Public Shared Function DoSomething2( ByVal value As String ) As Boolean
      Console.WriteLine( ControlChars.CrLf + "Callback called with _
          param: {0}", value )
      …
   End Function 'DoSomething2
End Class 'App

 
C#  复制代码 
public class App
{
   public static void Main()
   {
      FPtr cb = new FPtr( App.DoSomething );
      LibWrap.TestCallBack( cb, 99 );
      FPtr2 cb2 = new FPtr2( App.DoSomething2 );
      LibWrap.TestCallBack2( cb2, "abc" );
   }
   
   public static bool DoSomething( int value )
   {
      Console.WriteLine( "\nCallback called with param: {0}", value );
      …
   }
   public static bool DoSomething2( String value )
   {
      Console.WriteLine( "\nCallback called with param: {0}", value );
      …
   }   
}
 

请参见
概念
其他封送处理示例
平台调用数据类型
在托管代码中创建原型
发送反馈意见,就此主题向 Microsoft 发送反馈意见。
[解决办法]
可以的。
写了一个简单的例子


using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
    public delegate bool FPtr(int value);
    public delegate bool FPtr2(String value);

    public class LibWrap
    {// Declares managed prototypes for unmanaged functions.
        [DllImport("testlib.dll")]
        public static extern void TestCallBack(FPtr cb, int value);
        [DllImport("testlib.dll")]


        public static extern void TestCallBack2(FPtr2 cb2, String value);
        [DllImport("testlib.dll")]
        public static extern void TestCallBack3(String value);
    }
    class Program
    {
        static void Main(string[] args)
        {
            LibWrap.TestCallBack3("cb, 99");
 
            FPtr cb = new FPtr(DoSomething);

            LibWrap.TestCallBack(cb, 99);
            FPtr2 cb2 = new FPtr2(DoSomething2);
            LibWrap.TestCallBack2(cb2, "abc");
        }
 
        public static bool DoSomething(int value)
        {
            Console.WriteLine("\nCallback called with param: {0}", value);
            return false;
        }
        public static bool DoSomething2(String value)
        {
            Console.WriteLine("\nCallback called with param: {0}", value);
            return false;
        }
    }
}




c#调用代码
[解决办法]
引用:
我是这样做的,然后就抛出了


你是怎样做的?

要注意到,它(也许不经意间)使用了 public static 修饰符。

热点排行