如何包装模板函数,该功能以python的swig遵循可可的特征



我有一个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 中,可呼叫/谓词特征使我能够模板一种方法,以便我可以通过函数或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)。我试图创建一个函子包装器,例如:

%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)。

so:我需要添加到接口文件中,以利用python中的C 代码的可可特征?

这太通用了。如果您想将自己限制在std ::功能接口,例如

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并返回浮子。问题中的python代码应该只是工作。

上面的包装器是pyclif(而不是swig)。

最新更新