我有一个C++类,它的方法被模板化以遵循callable特征:
// 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函数、Cross-in Tray函数等。
该模式实际上非常标准:在C++中,callable/predicate特征允许我为一个方法提供模板,这样我就可以传递一个函数器或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语言中创建函数器的子类,在那里定义__call__
并使用它,但它只调用MyEvaluator::operator()
,这是没有意义的(而且可以理解,因为我将模板指定为使用MyEvaluator
)。
那么:为了利用Python中C++代码的可调用特性,我需要在接口文件中添加什么?
发布于 2017-11-01 06:24:46
这有点太笼统了。如果您想限制自己使用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)
并且可以通过任何接受MyObject并返回浮点数的Python函数调用。问题中的Python代码应该可以正常工作。
上面的包装器是PyCLIF (而不是SWIG)。
https://stackoverflow.com/questions/46338725
复制