将代码从 Delphi 翻译成 C++ Builder 10.3
Translate code from Delphi to C ++ Builder 10.3
parsing 有一个库。
我在项目中添加了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 Member function must be called or its address taken
如何申报活动?
在 C++ 中,数组属性不能仅在其索引类型上重载。因此,您将不得不重命名其中一个有问题的属性,没有其他选择。然后我建议你向库作者提交一份报告,要求使库对 C++ 用户更友好。
在 Delphi 代码中,TAlXMLParseTextEvent
是对 anonymous method:
的引用
TAlXMLParseTextEvent = reference to procedure (Sender: TObject; const Path, Str: AnsiString);
这就是它在 C++ 端被翻译成 __interface
的原因(因为匿名方法实际上是使用接口在幕后实现的)。 Delphi 风格的匿名方法需要在 C++ 中进行额外处理,如 Embarcadero 的 DocWiki 中所述:
How to Handle Delphi Anonymous Methods in C++
Under the cover, Delphi implements anonymous methods types (also known as method references) via an interface that implements an Invoke(...)
method.
So a method that takes a method reference parameter in Delphi is exposed to C++ as a method that takes an interface.
因此,您的 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 and Interfaces and Implementing Interfaces)来进一步简化仿函数的使用:
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-based compilers then you can use a C++ style 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);
};
}
parsing 有一个库。
我在项目中添加了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 Member function must be called or its address taken
如何申报活动?
在 C++ 中,数组属性不能仅在其索引类型上重载。因此,您将不得不重命名其中一个有问题的属性,没有其他选择。然后我建议你向库作者提交一份报告,要求使库对 C++ 用户更友好。
在 Delphi 代码中,TAlXMLParseTextEvent
是对 anonymous method:
TAlXMLParseTextEvent = reference to procedure (Sender: TObject; const Path, Str: AnsiString);
这就是它在 C++ 端被翻译成 __interface
的原因(因为匿名方法实际上是使用接口在幕后实现的)。 Delphi 风格的匿名方法需要在 C++ 中进行额外处理,如 Embarcadero 的 DocWiki 中所述:
How to Handle Delphi Anonymous Methods in C++
Under the cover, Delphi implements anonymous methods types (also known as method references) via an interface that implements an
Invoke(...)
method.So a method that takes a method reference parameter in Delphi is exposed to C++ as a method that takes an interface.
因此,您的 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 and Interfaces and Implementing Interfaces)来进一步简化仿函数的使用:
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-based compilers then you can use a C++ style 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);
};
}