TypeError: No to_python (by-value) converter found for C++ type

半腔热情 提交于 2020-01-24 01:46:25

问题


I'm trying to expose my C++ Classes to Python using Boost.Python. Here is a simplyfied version of what I'm trying to do:

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;
    }
};

I want to use above classes as follows in 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."

I didn't know any nice solution to this problem. I just tried this:

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();
    }
};

And them, I use following code:

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>());
}

But when I compiled above code into a .so file, and used in python

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

It throws out an exception:

TypeError: No to_python (by-value) converter found for C++ type: Base
  1. This post has the same error as mine, but in a different way, it didn't help me a lot. Boost.Python call by reference : TypeError: No to_python (by-value) converter found for C++ type:

  2. This post solves a similar problem, but didn't help me either. https://github.com/BVLC/caffe/issues/3494

I have two problems:

  1. If the way I tried is the right way, how to solve the TypeError problem?
  2. If I tried a wrong way, then what is the best way to solve the problem using boost.python?

回答1:


This code works for me:

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<>())
        ;
}

Testing module:

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


来源:https://stackoverflow.com/questions/41598229/typeerror-no-to-python-by-value-converter-found-for-c-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!