2015-12-15 2 views
2

Я использую следующий код, чтобы попытаться работать с векторами C++:Cython: C++ Используйте вектор в словаре?

from libcpp.vector cimport vector                                   

cdef struct StartEnd: 
    long start, end 

cdef vector[StartEnd] vect 
print(type(vect)) 
cdef int i 
cdef StartEnd j 
k = {} 
k['hi'] = vect 
for i in range(10): 
    j.start = i 
    j.end = i + 2 
    k['hi'].push_back(j) 
for i in range(10): 
    print(k['hi'][i]) 

Точная функциональность здесь не имеет значения, это просто манекен программы. Проблема заключается в том, что при запуске это порождает ошибку: AttributeError: 'list' object has no attribute 'push_back' Это работает, если нет словаря, но я считаю, что словарь необходим для моего использования. Есть ли способ сделать эту работу?

Я не хочу копировать векторы взад и вперед, поскольку эти векторы получат десятки миллионов записей. Может быть, я могу вместо этого сохранить указатели на вектор?

+1

что вы имеете в виду под "Это работает, если нет словаря? –

+1

@RNar Предположительно, что 'vect.push_back (...)' работает, но 'k ['hi']. Push_back (...)' does not. – user4815162342

+1

Попробуйте использовать 'k ['hi']' для вектора, используя ' (k ['hi']). Push_back (...)', как [описано здесь] (http: // docs.cython.org/src/reference/language_basics.html#type-casting). – user4815162342

ответ

3

Вектор C++ автоматически преобразуется в list на границе Cython/Python (следовательно, появляется сообщение об ошибке). Python dict ожидает хранения объектов Python, а не векторов C++. Создание cdef class, который содержит C++ вектор и положить, что в Словаре вместо:

cdef class VecHolder: 
    cdef vector[StartEnd] wrapped_vector 

    # the easiest thing to do is add short wrappers for the methods you need 
    def push_back(self,obj): 
    self.wrapped_vector.push_back(obj) 

cdef int i 
cdef StartEnd j 
k = {} 
k['hi'] = VecHolder() 
for i in range(10): 
    j.start = i 
    j.end = i + 2 
    k['hi'].push_back(j) # note that you're calling 
     # the wrapper method here which then calls the c++ function 
+0

Отличный ответ, спасибо. Я получил часть поиска для работы, сделав переменную wrapped_vector общедоступной, а затем выполнив 'print (k ['hi']. Wrapped_vector [i])' –

+1

Имейте в виду, что это скопирует вектор во временный список, когда вы это сделаете (что может быть медленным!). Определите '__getitem __ (self, idx)' на 'VecHolder', чтобы этого избежать (хотя вам все равно нужно подумать о том, как вы печатаете' StartEnd' ...) – DavidW

+0

Спасибо, я сделал это, и это сработало. Тем не менее, есть странная вещь: когда я напрямую работаю с конструкцией StartEnd, я обращаюсь к компонентам по точкам (например, 'j.start = i'), однако, когда я возвращаю структуру из вектора, это словарь , и я должен получить доступ так: 'k ['hi'] [i] ['start']', а не 'k ['hi'] [i] .start'. Я не уверен, что если это означает, что что-то идет не так (иначе структура была преобразована в объект python вместо сохранения в виде структуры C. Любые мысли? –

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