簡體   English   中英

將代碼從 Delphi 轉換為 C ++ Builder 10.3

[英]Translate code from Delphi to C ++ Builder 10.3

有一個用於解析的庫。

我在項目中添加了ALXmlDoc.pas ,C++Builder 在ALXmlDoc.pas第 177,178 行創建了ALXmlDoc.hpp

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 錯誤] Unit1.cpp (30): E2235 Member function 必須被調用或其地址被占用

如何申報活動?

在 C++ 中,不能僅在其索引類型上重載數組屬性。 因此,您將不得不重命名其中一個有問題的屬性,沒有其他選擇。 然后我建議您向庫作者提交報告,要求使庫對 C++ 用戶更友好。


在 Delphi 代碼中, TAlXMLParseTextEvent是對匿名方法的引用:

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

這就是為什么它被翻譯成__interface端的 __interface (因為匿名方法確實是使用接口在幕后實現的)。 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包裝器來進一步簡化仿函數的使用(請參閱Inheritance 和接口實現接口):

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)));
}

或者:

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);
    };
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM