从Delphi翻译代码到C ++ Builder 10.3

问题描述 投票:0回答:1

有一个库用于 解析.

我补充道 ALXmlDoc.pas 到项目中,C++Builder创建了 ALXmlDoc.hpp  在 ALXmlDoc.pas 177、178行。 

property Nodes [const Name: AnsiString]: TALXMLNode read GetNodeByName; default;
property Nodes [const Index: integer]: TALXMLNode read GetNodeByIndex; default;

ALXmlDoc.hpp

__property TALXMLNode * Nodes [const System :: AnsiString Name] = {read = GetNodeByName / *, default */};
__property TALXMLNode * Nodes [const int Index] = {read = GetNodeByIndex};

我得到一个关于复制的错误 - 如何解决?


.pas 705线

property OnParseText: TAlXMLParseTextEvent read FonParseText Write FonParseText; // [added from TXMLDocument]

ALXmlDoc.hpp:

__property _di_TAlXMLParseTextEvent OnParseText = {read = FonParseText, write = FonParseText};
__interface TAlXMLParseTextEvent: public System :: IInterface
{
    virtual void __fastcall Invoke (System :: TObject * Sender, const System :: AnsiString Path, const System :: AnsiString Str) = 0;
};
     
private:
    _di_TAlXMLParseTextEvent FonParseText;
protected:
    void __fastcall DoParseText (const System :: AnsiString Path, const System :: AnsiString Str);

 在我看来 Unit1.h

void __fastcall OnParseText (System :: TObject * Sender, const System :: AnsiString Path, const System :: AnsiString Str);

在我看来 Unit1.cpp

void __fastcall TForm1 :: OnParseText (System :: TObject * Sender, const System :: AnsiString Path, const System :: AnsiString Str)
{
    ShowMessage(Str); 
}
// ------------------------------------------------ ---------------------------
void __fastcall TForm1 :: Button1Click (TObject * Sender)
{
    TALXMLDocument * aXMLDocument = new TALXMLDocument ("root");
    aXMLDocument-> OnParseText = OnParseText;
}

我得到一个错误。 

[bcc32 Error] Unit1.cpp (30): E2235 成员函数必须被调用或其地址被占用。

如何声明一个事件?

delphi c++builder
1个回答
1
投票

在C++中,数组属性不能仅仅依靠其索引类型来重载。所以你必须重命名其中一个违规的属性,没有其他选择。 然后我建议你向库作者提交报告,要求让库对C++用户更友好。


在Delphi代码中。TAlXMLParseTextEvent 是指一个 匿名方法:

TAlXMLParseTextEvent = reference to procedure (Sender: TObject; const Path, Str: AnsiString);

这就是为什么它被翻译成一个 __interface Delphi式的匿名方法需要在C++中进行额外的处理,正如Embarcadero的DocWiki中所描述的那样:"在C++中,匿名方法是在幕后使用接口实现的。 Delphi风格的匿名方法需要在C++中进行额外的处理,这一点在Embarcadero的DocWiki上有记载。

如何在C++中处理Delphi匿名方法

的掩护下,Delphi通过一个接口实现了匿名方法类型(也称为方法引用),该接口实现了一个 Invoke(...) 方法。

因此,在Delphi中,一个采用方法引用参数的方法,在C++中被暴露为一个采用接口的方法。

因此,你的C++代码需要做一些更像这样的事情来代替。

struct TParseTextMethod
{
    void operator()(TObject *Sender, const AnsiString Path, const AnsiString Str)
    {
        ShowMessage(Str); 
    }
};
//------------------------------------------------ ---------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TALXMLDocument *aXMLDocument = new TALXMLDocument("root");

    // the TMethodRef functor is defined in the documentation,
    // you can copy/paste it as-is into your code...
    typedef TMethodRef<TAlXMLParseTextEvent,
                     TParseTextMethod,
                     void,
                     TObject *Sender,
                     const AnsiString,
                     const AnsiString> MyMethRef;

    aXMLDocument->OnParseText = _di_TAlXMLParseTextEvent(new MyMethRef(TParseTextMethod()));
}

或者,你也可以通过不使用这个函数来简化它的用法 TMethodRef 封装器 继承和接口实现接口):

class TParseTextMethod : public TCppInterfacedObject<TAlXMLParseTextEvent>
{
public:
    TParseTextMethod() {}
    INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);

    void __fastcall Invoke(TObject *Sender, const AnsiString Path, const AnsiString Str)
    {
        ShowMessage(Str); 
    }
};
//------------------------------------------------ ---------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TALXMLDocument *aXMLDocument = new TALXMLDocument("root");

    aXMLDocument->OnParseText = _di_TAlXMLParseTextEvent(new TParseTextMethod());
}

或者,如果你想继续使用你的 OnParseText() 方法,那么你就必须把它包在一个漏斗里面,比如说。

void __fastcall TForm1::OnParseText(TObject *Sender, const AnsiString Path, const AnsiString Str)
{
    ShowMessage(Str); 
}
//------------------------------------------------ ---------------------------
typedef void __fastcall (__closure *TAlXMLParseTextMethod)(TObject *Sender, const AnsiString Path, const AnsiString Str);

struct TParseTextMethod
{
    TAlXMLParseTextMethod Method;

    TParseTextMethod(TAlXMLParseTextMethod aMethod) : Method(aMethod) {}

    void operator()(TObject *Sender, const AnsiString Path, const AnsiString Str)
    {
        Method(Sender, Path, Str);
    }
};
//------------------------------------------------ ---------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TALXMLDocument *aXMLDocument = new TALXMLDocument("root");

    typedef TMethodRef<TAlXMLParseTextEvent,
                     TParseTextMethod,
                     void,
                     TObject *Sender,
                     const AnsiString,
                     const AnsiString> MyMethRef;

    aXMLDocument->OnParseText = _di_TAlXMLParseTextEvent(new MyMethRef(TParseTextMethod(&OnParseText)));
}

Or:

void __fastcall TForm1::OnParseText(TObject *Sender, const AnsiString Path, const AnsiString Str)
{
    ShowMessage(Str); 
}
//------------------------------------------------ ---------------------------
typedef void __fastcall (__closure *TAlXMLParseTextMethod)(TObject *Sender, const AnsiString Path, const AnsiString Str);

class TParseTextMethod : public TCppInterfacedObject<TAlXMLParseTextEvent>
{
public:
    TAlXMLParseTextMethod Method;

    TParseTextMethod(TAlXMLParseTextMethod aMethod) : Method(aMethod) {}
    INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);

    void __fastcall Invoke(TObject *Sender, const AnsiString Path, const AnsiString Str)
    {
        Method(Sender, Path, Str);
    }
};
//------------------------------------------------ ---------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TALXMLDocument *aXMLDocument = new TALXMLDocument("root");

    aXMLDocument->OnParseText = _di_TAlXMLParseTextEvent(new TParseTextMethod(&OnParseText));
}

或者,如果你使用的是某个 基于Clang的编译器 那么你可以用 C++风格的lambda 而不是一个漏斗。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TALXMLDocument *aXMLDocument = new TALXMLDocument("root");
    aXMLDocument->OnParseText = [](TObject*, const AnsiString, const AnsiString Str) {
        ShowMessage(Str);
    };
}

或:

void __fastcall TForm1::OnParseText(TObject *Sender, const AnsiString Path, const AnsiString Str)
{
    ShowMessage(Str); 
}
//------------------------------------------------ ---------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TALXMLDocument *aXMLDocument = new TALXMLDocument("root");
    aXMLDocument->OnParseText = [this](TObject *Sender, const AnsiString Path, const AnsiString Str) {
        OnParseText(Sender, Path, Str);
    };
}
© www.soinside.com 2019 - 2024. All rights reserved.