我有一个C ++类,其模板的方法是遵循可调用的特性:
// 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?
}
};
这里,MyOptimizationAlgorithm
类实现了一种优化算法。用户提供数据对象(双精度矢量,此处没有问题)和目标函数。此功能是优化算法所依赖的用户可配置部分。例如,有效的可调用评估器可以实现Ackley的功能,交叉托盘功能等。
模式实际上非常标准:在C ++中,可调用/谓词特征允许我模拟方法,以便我可以传递Functor或std::function
。如,
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) { /* ... */ });
我现在想用swig为Python创建一个包装器。当然,目标是在Python中创建赋值器函子并将其传递给C ++例程,如下所示:
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())
我是swig的新手。我已经收集到我需要专门化模板(使用%template
)并且我需要创建一个导演(%director
)。我试图创建一个Functor包装器,如下所示:
%inline %{
struct MyEvaluator
{
virtual double operator()(MyObject const& o) { return 0.0; }
virtual ~MyEvaluator() {}
};
%}
%feature("director") MyEvaluator;
%extend MyAlgorithm {
%template(runPredicated) optimize<MyEvaluator>;
}
我曾希望我可以在Python中创建我的Functor的子类,在那里定义__call__
并使用它,但它只调用MyEvaluator::operator()
,这是毫无意义的(并且可以理解,因为我专门用于使用MyEvaluator
)的模板。
那么:我需要在接口文件中添加什么来利用Python中C ++代码的可调用特性?
答案 0 :(得分:0)
这有点太通用了。如果你想限制自己使用std :: function接口,比如
class MyOptimizationAlgorithm
{
// ...
public:
// An optimization function that uses a user-supplied
// callable to evaluate a data object:
template<typename T>
void optimize(MyObject o, std::function<T(MyObject const&)> evaluator) {
// ... optimize, optimize, ...
T value = evaluator(o);
// ... are we good enough yet?
}
};
可能的包装器看起来像
class MyOptimizationAlgorithm:
def `optimize<double>` as optimize(o: MyObject, evaluator: (o: MyObject)->float)
并且可以使用任何Python函数调用MyObject并返回一个float。问题中的Python代码应该可以正常工作。
上面的包装器是PyCLIF(而不是SWIG)。