ich den folgenden Testfall gemacht zu veranschaulichen, was Sie zu tun versuchen. Es hat eine echte Umsetzung myfun(const std::vector<double(*)(double)>&)
, um das Leben ein wenig interessanter:
#include <vector>
double g(double x) {
return -x;
}
double f(double x) {
return x*x;
}
typedef double(*pfn_t)(double);
std::vector<double> myfun(const std::vector<pfn_t>& funs, const double d) {
std::vector<double> ret;
ret.reserve(funs.size());
for(auto && fn : funs)
ret.emplace_back(fn(d));
return ret;
}
ich erwartet, dass alles, was wir tun müssen, würde um diese Arbeit zu machen, ist die Verwendung:
%include <std_vector.i>
%template(FunVec) std::vector<double(*)(double)>;
%template(DoubleVec) std::vector<double>;
%include "test.h"
jedoch SWIG 3.0 (von Debian stable) behandelt dies FunVec
nicht korrekt und das resultierende Modul kompiliert nicht. So habe ich eine typemap als Behelfslösung:
%module test
%{
#include "test.h"
%}
%pythoncallback;
double f(double);
double g(double);
%nopythoncallback;
%ignore f;
%ignore g;
%typemap(in) const std::vector<pfn_t>& (std::vector<pfn_t> tmp) {
// Adapted from: https://docs.python.org/2/c-api/iter.html
PyObject *iterator = PyObject_GetIter($input);
PyObject *item;
if (iterator == NULL) {
assert(iterator);
SWIG_fail; // Do this properly
}
while ((item = PyIter_Next(iterator))) {
pfn_t f;
const int res = SWIG_ConvertFunctionPtr(item, (void**)(&f), $descriptor(double(*)(double)));
if (!SWIG_IsOK(res)) {
assert(false);
SWIG_exception_fail(SWIG_ArgError(res), "in method '" "foobar" "', argument " "1"" of type '" "pfn_t""'");
}
Py_DECREF(item);
tmp.push_back(f);
}
Py_DECREF(iterator);
$1 = &tmp;
}
%include <std_vector.i>
// Doesn't work:
//%template(FunVec) std::vector<double(*)(double)>;
%template(DoubleVec) std::vector<double>;
%include "test.h"
Grundsätzlich all dies tut, ist ein Add ‚in‘ typemap für den Vektor der Funktionszeigertypen. Diese Typumleitung iteriert einfach über die von Python gegebene Eingabe und erstellt ein temporäres std::vector
aus einem iterierbaren Python.
Dies ist ausreichend, dass die folgende Python wie erwartet funktioniert:
import test
print test.g
print test.f
print test.g(666)
print test.f(666)
print test.myfun([test.g,test.f],123)
@ πάντα ῥεῖ Das wichtigste Arbeitsbeispiel ist die gleiche, aber die Frage ist anders. Bitte entfernen Sie die Markierung als dup. –
Bitte verbessern Sie Ihre Frage 1st. –
Was ist unklar? –