【问题标题】:TypeError: No to_python (by-value) converter found for C++ typeTypeError:没有为 C++ 类型找到 to_python(按值)转换器
【发布时间】:2017-01-11 18:34:09
【问题描述】:

我正在尝试使用 Boost.Python 将我的 C++ 类公开给 Python。这是我正在尝试做的简单版本:

struct Base {
    virtual ~Base() {};
    virtual char const *Hello() {
        printf("Base.Hello\n");
        return "Hello. I'm Base.";
    };
};

struct Derived : Base {
    char const *Hello() {
        printf("Derived.Hello\n");
        return "Hello. I'm Derived.";
    };

    Base &test() {
        printf("Derived.test\n");
        // ...
        // After some calculation, we get result reference `instance'
        // `instance' can be an instance of Base or Derived.
        // ...
        return instance;
    }
};

我想在python中使用上面的类如下:

instance = Derived()

// If method test returns an instance of Base
instance.test().Hello() // Result: "Hello. I'm Base."

// If method test returns an instance of Derived
instance.test().Hello() // Result: "Hello. I'm Derived."

我不知道这个问题有什么好的解决方案。我刚试过这个:

struct BaseWrapper : Base, wrapper<Base> {
    char const *Hello() {
        printf("BaseWrapper.Hello\n");
        if (override Hello = this->get_override("Hello")) {
            return Hello();
        }
        return Base::Hello();
    }

    char const *default_Hello() {
        printf("BaseWrapper.default_Hello\n");
        return this->Base::Hello();
    }
};

struct DerivedWrapper : Derived, wrapper<Derived> {
    char const *Hello() {
        printf("DerivedWrapper.Hello\n");
        if (override Hello = this->get_override("Hello")) {
            return Hello();
        }
        return Derived::Hello();
    }

    char const *default_Hello() {
        printf("DerivedWrapper.default_Hello\n");
        return this->Derived::Hello();
    }

    Base &test() {
        printf("DerivedWrapper.test\n");
        if (override Hello = this->get_override("test")) {
            return Hello();
        }
        return Derived::test();
    }

    Base &default_test() {
        printf("DerivedWrapper.default_test\n");
        return this->Derived::test();
    }
};

而他们,我使用以下代码:

BOOST_PYTHON_MODULE(Wrapper) {
    class_<BaseWrapper, boost::noncopyable>("Base")
                .def("Hello", &Base::Hello, &BaseWrapper::default_Hello);

    class_<DerivedWrapper, boost::noncopyable, bases<Base> >("Derived")
            .def("Hello", &Derived::Hello, &DerivedWrapper::default_Hello)
            .def("test", &Derived::test,  return_value_policy<copy_non_const_reference>());
}

但是当我将上面的代码编译成.so文件,并在python中使用时

derived = Wrapper.Derived() 
derived.test()

抛出异常:

TypeError: No to_python (by-value) converter found for C++ type: Base
  1. 这篇文章的错误与我的相同,但以不同的方式,它对我没有多大帮助。 Boost.Python call by reference : TypeError: No to_python (by-value) converter found for C++ type:

  2. 这篇文章解决了一个类似的问题,但也没有帮助我。 https://github.com/BVLC/caffe/issues/3494

我有两个问题:

  1. 如果我尝试的方法是正确的,如何解决TypeError问题?
  2. 如果我尝试了错误的方法,那么使用 boost.python 解决问题的最佳方法是什么?

【问题讨论】:

    标签: python c++ boost polymorphism boost-python


    【解决方案1】:

    此代码适用于我:

    struct Base {
        virtual ~Base() {};
        virtual char const *hello() {
            return "Hello. I'm Base.";
        };
    };
    
    struct Derived : Base {
        char const *hello() {
            return "Hello. I'm Derived.";
        };
    
        Base &test(bool derived) {
            static Base b;
            static Derived d;
            if (derived) {
                return d;
            } else {
                return b;
            }
        }
    };
    
    BOOST_PYTHON_MODULE(wrapper)
    {
        using namespace boost::python;
        class_<Base>("Base")
            .def("hello", &Base::hello)
            ;
    
        class_<Derived, bases<Base>>("Derived")
            .def("test", &Derived::test, return_internal_reference<>())
            ;
    }
    

    测试模块:

    >>> import wrapper
    >>> d = wrapper.Derived()
    >>> d.test(True).hello()
    "Hello. I'm Derived."
    >>> d.test(False).hello()
    "Hello. I'm Base."
    >>>
    

    【讨论】:

    • 感谢您的解决方案,它确实解决了我的问题。我还找到了手册:link
    猜你喜欢
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 2019-02-10
    相关资源
    最近更新 更多