2013-12-23 3 views
0

принять этот кодКак скопировать список подталкивание питона или его ссылку с оператором «=»

#include<boost/python> 
namespace bp = boost::python; 

bp::list py_points; //initial list 
other_class* C; // this class have a bp::list attribute called py_list 

// ... some code .... 

// in this part C.py_list.ptr() is 0x0 

other_class->py_list = py_list; // problem here!! 

проблема с оператором «=»

в отладчике в файле object_core.hpp, это файл ядра подталкивание питон

inline api::object_base& api::object_base::operator=(api::object_base const& rhs) 
{ 
    Py_INCREF(rhs.m_ptr); 
    Py_DECREF(this->m_ptr); // in this line the program fail 
    this->m_ptr = rhs.m_ptr; 
    return *this; 
} 

что такое правильный способ использовать оператор «=»

отредактирован

проблема заключается в стек, если указатель other_class-> py_list равно нулю (или None, так как конструктор класса не вызывается) программа не могу назвать несильно Py_DECREF (Не существует ссылки до того указателя NULL)

проблема будет исправить вызов конструктора

other_class* C = new othe_class(); // fixed!! 

ответ

2

проблема не является оператором присваивания, проблема заключается в том, что внутренний PyObjectpy_list указатель «s является nullptr. В большинстве случаев указатель не должен быть нулевым. С точки зрения Python он должен по крайней мере управлять ссылкой на объект Python None, как это сделано по умолчанию построено boost::python::object. Конструктор по умолчанию для boost::python::list создает новый пустой список. Следовательно, источник проблемы, вероятно, находится либо в конструкторе other_class, либо в блоке «некоторый код».


Выработать на вопрос, поставленный в заголовке, создавая ссылку или копирование списка в Boost.Python такое же, как в Python:

  • Оператор присваивания создаст ссылку на список.

    >>> a = ['spam'] 
    >>> b = a 
    >>> b 
    ['spam'] 
    >>> a is b 
    True 
    
  • Каждый может slice список, чтобы создать неполную копию.

    >>> a = ['spam'] 
    >>> b = a[:] 
    >>> b 
    ['spam'] 
    >>> a is b 
    False 
    

Вот полный пример с эквивалентным кодом Python аннотированный в комментариях.

#include <iostream> 
#include <boost/python.hpp> 

/// @brief Mockup class. 
struct other_class 
{ 
    boost::python::list py_list; 
}; 

/// @brief Helper function to print object id and its string representation. 
std::string to_string(boost::python::object& o) 
{ 
    std::stringstream stream; 
    stream << o.ptr() << " = " 
     << boost::python::extract<std::string>(o.attr("__str__")())(); 
    return stream.str(); 
} 

int main() 
{ 
    using std::cout; 
    using std::endl; 
    namespace python = boost::python; 

    Py_Initialize(); 
    try 
    { 
    python::object object;       // object = None 
    cout << to_string(object) << "\n"     // print object 
     << " is none check: " << object.is_none() // print object is None 
     << endl; 

    // Create other_class and populate its list. 
    other_class* c = new other_class();    // py_list = [] 
    cout << "c->py_list: " << to_string(c->py_list) // print py_list 
     << endl; 
    c->py_list.append("spam");      // py_list.append("spam") 
    cout << "c->py_list: " << to_string(c->py_list) // print py_list 
     << endl; 

    // Have list1 reference c->py_list. 
    python::list list1;        // list1 = [] 
    cout << "list1: " << to_string(list1) << "\n"  // print list1 
     << "assign py_list to list1" << endl; 
    list1 = c->py_list;        // list1 = py_list 
    cout << "list1: " << to_string(list1) << endl;  // print list1 

    // Modify list1 and observe effects on pylist. 
    cout << "modify list1" << endl; 
    list1.append(42);         // list1.append(42) 
    cout << "c->py_list: " << to_string(c->py_list) // print py_list 
     << endl; 

    // Shallow-copy list1. 
    cout << "copying list1 into list2" << endl; 
    python::list list2(
     list1.slice(python::_, python::_));   // list2 = list1[:] 
    list2.append("eggs");        // list2.append("eggs") 
    cout << "list2: " << to_string(list2) << "\n"  // print list2 
     << "list1: " << to_string(list1) << endl;  // print list1 

    delete c; 
    } 
    catch (python::error_already_set&) 
    { 
    PyErr_Print(); 
    } 
} 

Выход:

0x804e1ac = None 
    is none check: 1 
c->py_list: 0xb707024c = [] 
c->py_list: 0xb707024c = ['spam'] 
list1: 0xb70da98c = [] 
assign py_list to list1 
list1: 0xb707024c = ['spam'] 
modify list1 
c->py_list: 0xb707024c = ['spam', 42] 
copying list1 into list2 
list2: 0xb707cb0c = ['spam', 42, 'eggs'] 
list1: 0xb707024c = ['spam', 42] 

Несколько пунктов отметить на выходе:

  • По умолчанию построено boost::python::list объектов управления ссылкой на пустой список. 0x804e1ac - None, и ни один внутренний указатель PyObject объекта списка не ссылается на него.
  • Назначение назначения list1 = py_list вызывает list1 для управления ссылкой на тот же список, которым управляет py_list.Это отображается на выходе list1, первоначально управляя ссылкой на 0xb70da98c, но после назначения он управляет ссылкой на 0xb707024c. С list1 и py_list, управляющими одним и тем же списком, изменение в списке через один дескриптор можно наблюдать в другом дескрипторе.
  • Нарезка построила новый список. Таким образом, внутренняя точка PyObject для list2 управляет различной ссылкой (0xb707cb0c), чем указатель list1 (0xb707024c).
+0

thaks много, я отредактировал сообщение немного – ljofre

Смежные вопросы