有一个库用于 解析.
我补充道 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 成员函数必须被调用或其地址被占用。
如何声明一个事件?
在C++中,数组属性不能仅仅依靠其索引类型来重载。所以你必须重命名其中一个违规的属性,没有其他选择。 然后我建议你向库作者提交报告,要求让库对C++用户更友好。
在Delphi代码中。TAlXMLParseTextEvent
是指一个 匿名方法:
TAlXMLParseTextEvent = reference to procedure (Sender: TObject; const Path, Str: AnsiString);
这就是为什么它被翻译成一个 __interface
Delphi式的匿名方法需要在C++中进行额外的处理,正如Embarcadero的DocWiki中所描述的那样:"在C++中,匿名方法是在幕后使用接口实现的。 Delphi风格的匿名方法需要在C++中进行额外的处理,这一点在Embarcadero的DocWiki上有记载。
的掩护下,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);
};
}