Ich habe eine C++ Klasse mit einer Methode, die dem aufrufbare Merkmale folgt Templat ist:Wie umschließt eine Template-Funktion, die der aufrufbaren Eigenschaft mit swig für Python folgt?
// A general data object
struct MyObject
{
// ... hold some data, parameters, ...
};
class MyOptimizationAlgorithm
{
// ...
public:
// An optimization function that uses a user-supplied
// callable to evaluate a data object:
template <class Callable> void optimize(MyObject o, Callable evaluator) {
// ... optimize, optimize, ...
auto value = evaluator(o);
// ... are we good enough yet?
}
};
Hier ist die MyOptimizationAlgorithm
Klasse implementiert einen Optimierungsalgorithmus. Der Benutzer liefert ein Datenobjekt (ein Doppelvektor, hier kein Problem) und eine Zielfunktion. Diese Funktion ist der vom Benutzer konfigurierbare Teil, auf den sich der Optimierungsalgorithmus stützt. Zum Beispiel könnten gültige aufrufbare Evaluatoren die Ackley-Funktion, die Cross-in-Tray-Funktion usw. implementieren.
Das Muster ist eigentlich ziemlich standardisiert: In C++ erlaubt mir das Callable/Prädikat-Merkmal, eine Methode zu erstellen, die ich weitergeben kann ein Functor oder ein std::function
. ZB
struct Ackley
{
double operator()(MyObject const& o)
{
return /* ackley() applied to the values in o */
}
};
MyOptimizationAlgorithm optimizer;
MyObject initialData;
// ... supply data,
// ... tune some parameters of the optimizer, then:
optimizer.optimize(initialData, Ackley());
// ... or:
optimizer.optimize(initalData, [](MyObject const& o) { /* ... */ });
Ich möchte jetzt einen Wrapper für Python mit swig erstellen. Das Ziel ist natürlich, die Auswerter Funktors in Python zu erstellen und an die Routine C++ übergeben, etwa so:
def CrossInTray:
def __call__(self, obj):
# calculate the cross-in tray function.
optimzer = MyOptimizationAlgorithm()
initial_data = MyObject()
# ... again, setup, then:
optimizer.optimize(initial_data, CrossInTray())
Ich bin neu in swig. Ich habe gesammelt, dass ich die Vorlage (unter Verwendung %template
) spezialisieren muss und dass ich einen Direktor (%director
) erstellen muss. Ich habe versucht, einen Functor Wrapper zu erstellen, etwa so:
%inline %{
struct MyEvaluator
{
virtual double operator()(MyObject const& o) { return 0.0; }
virtual ~MyEvaluator() {}
};
%}
%feature("director") MyEvaluator;
%extend MyAlgorithm {
%template(runPredicated) optimize<MyEvaluator>;
}
Ich hatte gehofft, dass ich dann Subklassen meines Functor in Python erstellen könnte, definieren __call__
dort und habe es verwendet, aber es ruft nur MyEvaluator::operator()
, das ist ziemlich sinnlos (und verständlich, da ich die Vorlage auf MyEvaluator
spezialisiert habe).
Also: Was muss ich der Schnittstellendatei hinzufügen, um die aufrufbare Eigenschaft von C++ - Code in Python zu verwenden?
Die Eigenschaft kann niemals mit einer Python-Implementierung realisiert werden, '% template (runPredicated) optimiert;' ist eine Template-Instanziierung und zum Zeitpunkt der Instanziierung muss 'MyEvaluator' bekannt sein. Was Sie einfach tun können, ist eine Schnittstelle in 'C++' definiert, implementieren Sie diese in Python und verwenden Sie diese in C++ und sogar in einem C++ - Programm, siehe https://stackoverflow.com/questions/9040669/how-can-i-implement -ac-class-in-python-zu-called-by-c/9042139 –