LINUX.ORG.RU

Проблема с cython

 ,


0

2

Немного играюсь с cython'ом. Решил написать небольшой враппер, скармливающий данные одной библиотеке, столкнулся с небольшой проблемой.

Код враппера:

# -*- coding: utf-8 -*-

#cython: wraparound=False
#cython: boundscheck=False

from cpython cimport array
import array

ctypedef public struct qmmmdata:
    int atomNR
    int* labels

cdef void gen_input_data(qmmmdata *data):

    cdef int N = 5
    cdef array.array labels = array.array('i', [6, 4, 6, 1, 1])

    data.atomNR = N

    data.labels = labels.data.as_ints

    print 'Before'

    print 'Atom N:', data.atomNR

    print 'Labels:', [data.labels[i] for i in range(data.atomNR)]

cdef void print_result(qmmmdata *data):

    print 'After'

    print 'Atom N:', data.atomNR

    print 'Labels:', [data.labels[i] for i in range(data.atomNR)]

cdef void do_work():

    cdef qmmmdata data
    gen_input_data(&data)
    print_result(&data)

if __name__ == '__main__':

    do_work()

И запускаю вот так:

$ rm -f test_array.c test_array.h test_array.exe
$ cython --embed test_array.pyx
$ gcc test_array.c -I/usr/include/python2.7 -L/usr/lib -lpython2.7 -o test_array.exe
$ ./test_array.exe
Before
Atom N: 5
Labels: [6, 4, 6, 1, 1]
After
Atom N: 5
Labels: [159730576, 4, 6, 1, 1]

Возможно ЛОР сможет подсказать причину изменения содержимого переменной data.labels? Если реализовать этот кусок иначе, например с numpy массивами и передачей указателей на них, то все ок. Но теперь интересует причина проблем в этом месте.

★★★★★

Навскидку: у тебя "cdef array.array labels" подчищается при выходе из gen_input_data. Ты это прям в сишном выхлопе можешь посмотреть.

A1 ()

Вообще если задача сделать только враппер, то cffi гораздо проще. Использовать cython имеет смысл только если надо узкий код самому написать.

A1 ()

А если просто отпринтить питоновским принтом этот data.labels? Без генератора списков. И что будет, если генератор заменить на цикл? В функции gen input data.

menangen ★★★★★ ()
Ответ на: комментарий от A1

Ну там история сложнее немного: есть хороший и производительный пакет для расчетов на C/C++, который будет линковаться с нашей библиотекой на cython. Просто чтобы не дергать каждый раз этот пакет (пока инициализируется mpi, пока загрузятся данные...) захотелось написать небольшой враппер.

silw ★★★★★ ()
Ответ на: комментарий от menangen

Генератор/список - никакой разницы.

Ну и отпринтить тоже не получится:

Error compiling Cython file:
------------------------------------------------------------
...

    print 'Atom N:', data.atomNR

    print 'Labels:'

    print data.labels
             ^
------------------------------------------------------------

test_array.pyx:28:14: Cannot convert 'int *' to Python object
make: *** [test_array] Error 1

silw ★★★★★ ()
Ответ на: комментарий от silw

Этот путь не отменяет питонячью семантику с gc. Владение то не передается.

Как вариант:

# -*- coding: utf-8 -*-
#cython: wraparound=False
#cython: boundscheck=False

from cpython cimport array
import array

ctypedef public struct qmmmdata:
    int atomNR
    int* labels

cdef void gen_input_data(qmmmdata *data, array.array labels):
    cdef int N = 5
    data.atomNR = N
    data.labels = labels.data.as_ints

    print 'Before'
    print 'Atom N:', data.atomNR
    print 'Labels:', [data.labels[i] for i in range(data.atomNR)]

cdef void print_result(qmmmdata *data):
    print 'After'
    print 'Atom N:', data.atomNR
    print 'Labels:', [data.labels[i] for i in range(data.atomNR)]

cdef void do_work():
    cdef array.array labels = array.array('i', [6, 4, 6, 1, 1])
    cdef qmmmdata data
    gen_input_data(&data, labels)
    print_result(&data)

if __name__ == '__main__':
    do_work()
A1 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.