использование cpp карт со значениями массива в Cython - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь построить карту с целочисленными значениями в качестве ключей и списками целых чисел в качестве значений. Я написал следующий файл test.pyx:

from libcpp.map cimport map as cmap
import array
from libcpp.pair cimport pair as cpair
from cpython cimport array

cdef cmap[int, int[:]] dict_to_cmap(dict the_dict):
    cdef int map_key
    cdef int[:] map_val
    cdef cpair[int, int[:]] map_element
    cdef cmap[int, int[:]] my_map
    for key,val in the_dict.items():
        map_key = key
        map_val = array.array('i', val)
        map_element = (map_key, map_val)
        my_map.insert(map_element)
    print("values are:")
    print(my_map[1], my_map[1][0])
    print(my_map[2], my_map[2][0])
    return my_map

def test():
    the_dict = {1:[1], 2:[1]}
    dict_to_cmap(the_dict)

Когда я компилирую этот код с:
python test_setup.py build_ext --inplace
И запускаю его с:
python -c "import test; test.test()"

Результат:

values are:
(<MemoryView of 'NoneType' at 0x7f018b837be0>, -1954556344)
(<MemoryView of 'NoneType' at 0x7f018b837d88>, 1)

Как видите, один из результатов поврежден. Что я делаю неправильно? Похоже, это как-то связано с int[:].

1 Ответ

0 голосов
/ 23 февраля 2020

Просмотр памяти Cython не владеет данными, это просто просмотр памяти. Вы не должны передавать представление array на карту C ++, потому что объект array будет, наконец, подвергаться сборке мусора Python. Вот почему вы получили результат просмотра на None. Итак, кто должен владеть данными и управлять подсчетом ссылок? - C ++

Вот рабочий:

from libcpp.map cimport map as cmap
from libcpp.pair cimport pair as cpair
from libcpp.vector cimport vector

cdef cmap[int, vector[int]] dict_to_cmap(dict the_dict):
    cdef int map_key
    cdef vector[int] map_val
    cdef cpair[int, vector[int]] map_element
    cdef cmap[int, vector[int]] my_map
    for key,val in the_dict.items():
        map_key = key
        map_val = val  # list values will be copied to C++ vector
        map_element = (map_key, map_val)
        my_map.insert(map_element)
    return my_map

def test():
    the_dict = {1:[1, 2, 3], 2:[4, 5, 6]}
    print(dict_to_cmap(the_dict))  # Cython will automatically convert the C++ map to a Python dict
...