在 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++
实际上,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 and Interfaces 和 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 之一,那么您可以使用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);
};
}