7

我有一个类似于下面的类结构,其中我有两种类型 A 和 B 具有相似的签名,只是参数/返回类型不同。然后我使用一个类模板来处理这两个类,在 Python 中实现了鸭式的静态变体。现在我想用 pybind11 将这段代码包装到 Python 中,我希望在其中得到一个使用标准动态鸭子类型的类。我该怎么做呢?

我基本上是在寻找一种方法来禁用 pybind11 中的严格类型检查或指定多种类型,以便同时接受 TypeA 和 TypeB。下例定义的方式,只有TypeA通过检查。由于函数签名不同,我也无法将 A 和 B 统一为基类。

#include <pybind11/pybind11.h>
#include <iostream>

class TypeA {
public:
    typedef double InType;
    typedef std::string OutType;
    const OutType operator()(const InType arg)
    {
        return std::to_string(arg);
    }
};

class TypeB {
public:
    typedef std::string InType;
    typedef double OutType;
    const OutType operator()(const InType arg)
    {
        return std::stod(arg);
    }
};

template<typename T>
class DuckType {
public:
    void runType(const typename T::InType arg)
    {
        T x;
        const typename T::OutType y = x(arg);
        std::cout << y << std::endl;
    }
};

namespace py = pybind11;

PYBIND11_PLUGIN(ducktyping) {

    pybind11::module m("ducktyping", "Testing ducktyping with templates");

    typedef DuckType<TypeA> Type;
    py::class_<Type>(m, "DuckType")
    .def("run_type", &Type::runType);
    ;
    return m.ptr();
}
4

2 回答 2

1

如果您要绑定的函数具有可以在 C++ 中“驱动”推理的参数,您可能会使用它们来驱动重载决议pybind11https ://pybind11.readthedocs.io/en/stable/advanced/functions.html#重载解决顺序

例如,您可以将您的实例化绑定为重载,然后让它pybind11解决:

// Let's say `DuckType::runType` is static.
m.def("runType", &DuckType<TypeA>::runType, py::arg("arg"));
m.def("runType", &DuckType<TypeB>::runType, py::arg("arg"));

然后调度将在 Python 中工作,假设用户可以实例化这些类型,并且InTypes 被定义为不会意外拦截另一个类的类型:

runType(arg=1.2)  # TypeA
runType(arg="hello world")  # TypeB
于 2019-06-18T12:30:43.427 回答
0

可以在以下 github 问题中找到一个示例

https://github.com/pybind/pybind11/issues/199#issuecomment-323995589

我将在此处复制示例以完成

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

namespace py = pybind11;

template <typename T>
class MyClass : public SuperClass
{
 MyClass(int foo)   {}
 void func (int baa)
}

template <typename T>
void MyClass<T> :: func(int baa) {}

PYBIND11_MODULE(example, m) {
py::class_< MyClass<double>, shared_ptr< MyClass<double> >, SuperClass>(m, "MyClass")
 .def(py::init<int>())
 .def("func", &MyClass<double>::func);
}
于 2021-05-26T07:02:23.880 回答