Как передать объект C++ другому объекту C++ с помощью Boost.Python

У меня есть код C++, который определяет два класса, A и B. B принимает экземпляр A во время построения. Я обернул A с помощью Boost.Python, чтобы Python мог создавать экземпляры A, а также подклассы. Я хочу сделать то же самое с Б.

class A {
    public:
        A(long n, long x, long y) : _n(n), _x(x), _y(y) {};
        long get_n() { return _n; }
        long get_x() { return _x; }
        long get_y() { return _y; }
    private:
        long _n, _x, _y;
};

class B {
    public:
        B(A a) : _a(a) {};
        doSomething() {... };
    private:
        A _a;
};

Во время упаковки B мне нужно было решить, как передать экземпляр A конструктору B. Я немного покопался, и решение , которое я нашел, состояло в том, чтобы написать класс "преобразователя":

struct A_from_python_A {
    static void * convertible(PyObject* obj_ptr) {
        // assume it is, for now...
        return obj_ptr;
    }

    // Convert obj_ptr into an A instance
    static void construct(PyObject* obj_ptr,
                      boost::python::converter::rvalue_from_python_stage1_data* data) {
        // extract 'n':
        PyObject * n_ptr = PyObject_CallMethod(obj_ptr, (char*)"get_n", (char*)"()");
        long n_val = 0;
        if (n_ptr == NULL) {
            cout << "... an exception occurred (get_n)..." << endl;
        } else {
            n_val = PyInt_AsLong(n_ptr);
            Py_DECREF(n_ptr);
        }

        // [snip] - also do the same for x, y

        // Grab pointer to memory into which to construct the new A
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage*)
            data)->storage.bytes;

        // in-place construct the new A using the data
        // extracted from the python object
        new (storage) A(n_val, x_val, y_val);

        // Stash the memory chunk pointer for later use by boost.python
        data->convertible = storage;
    }

    // register converter functions
    A_from_python_A() {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id());
    }
};

Затем я регистрирую это с помощью:

BOOST_PYTHON_MODULE(interpolation_ext)
{
    // register the from-python converter for A
    A_from_python_A();

    class_("A", init())
        ;

    class_("B", init())
        ;
}

Конвертируемый и конструктивный методы — это методы, отвечающие на вопрос «это конвертируемый?» и "как преобразовать?" вопросы соответственно. Я заметил, что метод построения ()не является -тривиальным -, он должен обращаться к PyObject A *, извлекать все соответствующие поля, затем перестраивать экземпляр C++, который затем передается конструктору B. Поскольку A содержит некоторые частные поля, он должен делать это через механизмы общего доступа (, тогда как с чистым объектом Python этого не требуется, верно? ). Кажется, это работает.

Однако,Действительно ли необходимо извлечение поля в функции «конструировать»? Это кажется трудоемким. Если A является составным объектом, это может стать очень сложным и, возможно, потребовать, чтобы один преобразователь вызывал другой. Возможно, я понимаю требование, если A является классом Python, но если экземпляр A создан на стороне C++, есть ли способ определить, что это так, а затем просто получить дескриптор (, например. указатель )на этот «родной» объект в качестве ярлыка?

Вот соответствующий код Python:

from my_ext import A, B
a = A(1,2,3)
b = B(a)
b.doSomething()

8
задан davidA 12 August 2012 в 22:25
поделиться