3

异步回调函数

观点:我正在将几个 VB6 ActiveX 应用程序升级到 C#.net,它们都使用回调函数相互通信,它们向引用的 VC++.net 可执行文件注册。

我无法在 C# 中复制以下 VB6 功能: VB6 将包含方法的实例化类作为回调函数参数传递给 VC++ 的能力,然后 VC++ 将其注册为异步通信的回调函数。

除了这个问题之外,升级进行得非常好: 回调函数 ……我现在已经坚持了两个星期。请帮我!!!

我已经弄清楚如何将回调函数作为委托传递,我已经设法使用 C# DynamicInvoke,但是我真的需要它才能在 VC++ 中工作。

我从VC++语句中不断收到的错误消息是"Invalid Number of Parameters" invoke


下面我概述了处理异步回调的 VB6 和 VC++ 功能。每个 VB6 ActiveX 组件都将一个包含单个方法的类作为回调函数传递给 VC++ 可执行文件,VC++ 可执行文件将回调保存在一个数组中供以后使用。由于这是现有代码,因此可以按预期工作。

以下是被实例化并用作回调的VB6类: 请注意:Class1
Attribute Notify.VB_UserMemId = 0

VERSION 1.0 CLASS
BEGIN
 MultiUse = -1       
 Persistable = 0 
 DataBindingBehavior = 0 
 DataSourceBehavior  = 0 
 MTSTransactionMode  = 0 
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
 
Sub Notify(ByVal message As Integer, ByVal data As Variant)
Attribute Notify.VB_UserMemId = 0
  MsgBox Str$(message) + "  " + data, vbInformation, Form1.Text2
End Sub

上面的代码已被简化以避免混淆。

下面是实例化 VC++ 可执行文件 () 的VB6代码,VCCallbackHandler并将实例化的对象Class1作为回调参数传递给它

Dim VCCallbackHandler New VCCallbackHandler.VCCallbackHandler 
Dim c1 As New Class1

Private Sub Register_Click()
   Dim i as int
   i = VCCallbackHandler.Register(c1, "NameOfApplication")
End Sub

VC++ 代码注册回调(见下文),然后(异步)VC++ 可以利用回调,如果由其他事件提示(见下文'BroadCast')。在这种情况下,VC++ exe 充当多个同时运行的应用程序的中央回调处理程序。每个应用程序都向 VC++ 回调处理程序注册了它们的回调,并且当一个应用程序通过调用另一个事件来提示 VC++ 回调处理程序时,将调用所有回调。通过这种方式,回调处理程序允许所有这些其他应用程序相互通信。

下面是相关的VC++.Net回调代码。

注册回调:

 #define MAXREG  20

 typedef struct tagRegElement {
    char    name[20];       // Name of registered application
    _Callback   *p_Callback;    // Callback wrapper class
 } REG_ELEMENT;

public:
     REG_ELEMENT Registry[MAXREG];


short CBreqDlgAutoProxy::Register(LPDISPATCH callback, LPCTSTR name) 
{
    for (int i = 0;i<MAXREG;i++){
        if(!(theApp.Registry[i].name[0]))
        {
            RegIndex = i;
            strcpy(theApp.Registry[i].name,name);
            theApp.Registry[i].p_Callback = new _Callback(callback);
            return i;
        }
    }
 
    return -1;
 }

调用回调:

 BOOL CBreqDlgAutoProxy::Broadcast(short message, const VARIANT FAR& data) 
 {
    for (int i = 0;i<MAXREG;i++){
        if(theApp.Registry[i].name[0] && (i != RegIndex)){
            if (!theApp.Registry[i].p_Callback->Notify(message,data,theApp.Registry[i].name))
                DeRegister(i);
        }
    }
    
    return TRUE;
 }

 BOOL _Callback::Notify(short message, VARIANT data, char* RegisteredName)
 {
    static BYTE parms[] = VTS_I2 VTS_VARIANT;
        
    InvokeHelper(0x0, DISPATCH_METHOD, VT_EMPTY, NULL, parms, message, &data);
     
    return TRUE;
 }

笔记。 以上工作。

有两种可能的解决方案:

  1. C#:如何让 C# 将方法作为参数传递。我想出了如何使用委托来做到这一点,但是 VC++ 想要一个方法而不是委托。
  2. VC++:如何让 VC++ 处理委托而不是方法作为要调用的回调。

我对以下任何c#代码片段都没有成功:`

  • Marshal.GetFunctionPointerForDelegate
  • GCHandle
  • KeepAlive

我希望那里有人遇到过这个问题,并且可以去...... SNAP......它很容易......使用这个......交叉手指。

4

1 回答 1

0

我以前做过类似的事情,但我用它来传递变量。

C#:如何让 C# 将方法作为参数传递。我想出了如何使用委托来做到这一点,但是 VC++ 想要一个方法而不是委托。

我曾使用 C++/CLI,因为 C# 代码(托管)不能直接与 VC++ 代码(非托管)对话。

因此,如果您可以编写 CLI/C++ 包装器,那将有所帮助。

PS。我想知道如何将委托传递给 VC++。如果您可以发布代码,那就太好了。

于 2011-05-05T06:03:01.497 回答