C++Builder 控制台应用程序:链接到基于 __closure 的方法

C++Builder Console application: linking to a __closure based method

首先,请原谅我的标题。不太确定如何问这个问题:

我有一个应用程序需要转换为控制台应用程序(注意该应用程序作为 VCL 样式 windows 应用程序运行良好)。该应用程序使用一些具有回调函数的第 3 方小部件。但是,当我尝试编译它时,出现 'cannot convert ...' 错误,如下所示:

Cannot convert 'void(Tobject *, TErrorEventParams *)' to 'TErrorEvent'

TErrorEvent 定义为:

typedef void __fastcall (__closure* TErrorEvent)(System::TObject* Sender, TErrorEventParams *e);

导致错误的行是:

handler->OnError = errorHandler;

errorHandler 的代码是:

void __fastcall errorHandler(System::TObject* Sender, TErrorEventParams *e)
{
    memoLine = e->Description;
    updateLog();
}

查看此文档:

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Closure

简而言之:

TErrorEvent 被定义为指向 class 成员函数的指针。所以 errorHandler 必须声明为 class 成员函数。

实现可能看起来像这样:

class TMyClass
{
private:
    TMyHandler* handler;
    void __fastcall errorHandler(System::TObject* Sender, TErrorEventParams *e);
public:
    __fastcall TMyClass();
} my_dummy_class;

__fastcall TMyClass::MyClass()
{
    //handler has to be created
    handler->OnError = errorHandler; 
}

void __fastcall TMyClass::errorHandler(System::TObject* Sender, TErrorEventParams *e)
{
    memoLine = e->Description;
    updateLog();
}

A __closure 类型是指向 non-static class 方法的指针。编译器不允许您在需要 __closure 的地方分配独立的 non-class 函数。它需要一个指向 class 对象方法的指针。 Karem 的回答向您展示了一种实现该目标的方法。

但是,一种使用non-class函数的方法,使用助手TMethod结构(__closure在幕后实施)。

首先,向您的事件处理程序添加一个明确的 'this' 参数:

void __fastcall errorHandler(void *This, TObject* Sender, TErrorEventParams *e)
{
    memoLine = e->Description;
    updateLog();
}

然后像这样分配事件处理程序:

TMethod m;
m.Code = &errorHandler
m.Data = NULL; // any value you want to pass to the 'This' parameter...
handler->OnError = reinterpret_cast<TErrorEvent&>(m);