Comment gérer les méthodes anonymes Delphi dans C++
Remonter à Gestion des fonctionnalités Delphi dans C++Builder - Index
Cette rubrique décrit comment gérer les méthodes anonymes Delphi dans le code C++.
Sommaire
Implémentation des types de méthode anonyme Delphi
Delphi implémente les types de méthodes anonymes (aussi connus comme des références de méthode) via une interface qui implémente une méthode Invoke(...)
.
Ainsi une méthode qui prend un paramètre référence de méthode dans Delphi est exposée dans C++ comme une méthode qui prend une interface. Par exemple :
interface
type
TFilterPredicate = reference to function(const Path: string;
const SearchRec: TSearchRec): Boolean;
// …
class function GetFiles(const Path: string; const Predicate: TFilterPredicate):
TStringDynArray; overload; inline; static;
Le code suivant est le fichier d'en-tête C++ fourni par RAD Studio pour l'exemple ci-dessus :
typedef System::DelphiInterface<TFilterPredicate> _di_TFilterPredicate;
__interface TFilterPredicate : public System::IInterface
{
virtual bool __fastcall Invoke(const System::UnicodeString Path,
const System::Sysutils::TSearchRec &SearchRec) = 0 ;
};
// …
static System::TStringDynArray __fastcall GetFiles(const System::UnicodeString
Path, const _di_TFilterPredicate Predicate)/* overload */;
Comme illustré ci-dessus, TFilterPredicate
est exposé sous la forme d'une interface côté C++. Le code C++ qui effectue une opération seek pour spécifier une fonction ou une fonction membre comme paramètre référence de méthode doit envelopper la dernière derrière une interface qui expose la méthode Invoke()
.
Gestion des types de méthode anonyme dans C++
Utilisation d'une expression lambda
Si vous utilisez un compilateur C++ amélioré par Clang, vous pouvez utiliser une expression lambda chaque fois qu'une API Delphi attend une méthode anonyme Delphi. La classe DelphiInterface s'auto-convertit automatiquement en expression lambda.
Par exemple :
#include <System.hpp>
#include <System.IOUtils.hpp>
#include <iostream>
int main()
{
String ext(".cpp");
TStringDynArray files = TDirectory::GetFiles(TDirectory::GetCurrentDirectory(),
[ext](const String Path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
return ExtractFileExt(SearchRec.Name) == ext;
});
std::cout << "Found " << files.Length
<< " files with ext: '" << AnsiString(ext).c_str() << "'\n";
for (int i=0; i<files.Length; ++i)
std::cout << AnsiString(files[i]).c_str() << std::endl;
}
Utilisation d'un foncteur (objet fonction)
Un template C++ peut être utilisé pour l'encapsulation d'une interface qui expose une méthode Invoke().
Le code C++ suivant montre un exemple d'un template qui peut être utilisé pour transmettre des fonctions membre ou des méthodes C++ en tant que références de méthode à Delphi :
#include <System.hpp>
enum _DummyType{}; // Parameter used as default
template <typename INTF, // Interface with Invoke
typename F, // Functor type
typename R, // Return type
typename P1 = _DummyType, // Param #1
typename P2 = _DummyType, // Param #2
typename P3 = _DummyType, // Param #3
typename P4 = _DummyType, // Param #4
typename P5 = _DummyType> // Param #5
class TMethodRef : public TCppInterfacedObject<INTF>
{
private:
F callback;
public:
TMethodRef(F _callback) : callback(_callback) {}
INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);
R __fastcall Invoke(P1 p1) {
return callback(p1);
}
R __fastcall Invoke(P1 p1, P2 p2) {
return callback(p1, p2);
}
R __fastcall Invoke(P1 p1, P2 p2, P3 p3) {
return callback(p1, p2, p3);
}
R __fastcall Invoke(P1 p1, P2 p2, P3 p3, P4 p4) {
return callback(p1, p2, p3, p4);
}
R __fastcall Invoke(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
return callback(p1, p2, p3, p4, p5);
}
};
Le code suivant vous montre comment utiliser le modèle affiché ci-dessus pour appeler GetFiles :
#include <System.IOUtils.hpp>
#include <iostream>
struct Filter {
Filter(String _ext) : ext(_ext)
{}
bool operator()(const System::UnicodeString, const System::Sysutils::TSearchRec &SearchRec) {
return ExtractFileExt(SearchRec.Name) == ext;
}
String ext;
};
int main()
{
typedef TMethodRef<TDirectory::TFilterPredicate,
Filter,
bool,
const System::UnicodeString,
const System::Sysutils::TSearchRec&> MyMethRef;
String ext(".cpp");
TStringDynArray files = TDirectory::GetFiles(TDirectory::GetCurrentDirectory(),
TDirectory::_di_TFilterPredicate(new MyMethRef(Filter(ext))));
std::cout << "Found " << files.Length
<< " files with ext: '" << AnsiString(ext).c_str() << "'\n";
for (int i=0; i<files.Length; ++i)
std::cout << AnsiString(files[i]).c_str() << std::endl;
}