Найти - Пользователи
Полная версия: Pyrex/Cython, результат cdef метода
Начало » Python для экспертов » Pyrex/Cython, результат cdef метода
1
bw
Всем привет.
Возникла проблема с Pyrex/Cython, похоже это баг.
Из cdef void bar метода вызываю cdef void* foo метод (функцию), результат сохраняю в локальных переменных или еще где, это не имеет значения. foo выполнен в двух видах, как функция (не привязан к классу) и как метод класса. Оба метода foo компилируются в ожидаемый C-код, т.е. нет никакого упоминания PyObject, обычный C. Первый foo из bar вызывается нормально и результат присваевается чему надо, а вот со вторым проблема. Второй метод bar вызывает как питоновский, т.е. запрашивает его по имени (PyObject_GetAttr) и вызывает (PyObject_Call), что неправильно, в словаре foo просто не будет (на сколько я понимаю). Более того Pyrex/Cython думает (в методе bar), что результат этого метода это PyObject (что не верно) и, естественно, не может преобразовать его к требуемому void*. Напомню, с первым foo проблем нет.

test.pyx:
cdef class A:

cdef void* foo(self):
return NULL


cdef void* foo():
return NULL


cdef void bar(object a):
cdef void* b
b = foo()
b = a.foo()
Ошибка возникает в последней строчке (b = a.foo()), она у меня идет 16'ой.

test.py
#!/usr/bin/env python

from distutils.core import setup
from distutils.extension import Extension
#from Pyrex.Distutils import build_ext
from Cython.Distutils import build_ext


setup(
name = 'test',
ext_modules=[Extension('test', ['test.pyx'])],
cmdclass = {'build_ext': build_ext})
Собираем это дело командой: ./test.py build_ext –inplace

Ошибка:
Error converting Pyrex file to C:
------------------------------------------------------------
...

cdef void bar(object a):
cdef void* b
b = foo()
b = a.foo()
^
------------------------------------------------------------

./test.pyx:16:10: Cannot convert Python object to 'void *'
Подскажите, как с этим бороться? Как мне вызвать cdef void* foo экземпляра класса и получить void*, а не какой-то там PyObject?

..bw
estin
>>Подскажите, как с этим бороться? Как мне вызвать cdef void* foo экземпляра класса и получить void*, а не какой-то там PyObject?
.. bar(object a)

object - как раз и говорит что будет pyObject… вроде как :)

в функцию bar что должно передаваться?
__Объект__ (Python) или __Экземпляр__Структуры__ cdef class A
bw
estin
.. bar(object a)

object - как раз и говорит что будет pyObject… вроде как :)
Никто и не спорит, что a является PyObject, но это не относится к a.foo, и к результату этого метода.

estin
в функцию bar что должно передаваться?
__Объект__ (Python) или __Экземпляр__Структуры__ cdef class A
PyObject, не обращай внимание на это, дело не в том, что передается bar, а то, что возвращается foo в его будущности методом класса, а не глобальным методом, не смотря на то, что в действительности он не компилируется как полноценный Python-метод, т.е. доступ к нему возможен, только из Pyrex/Cython и линкуемого “Сишного” кода. При интерпретации этот метод не будет виден, он является, так сказать compile-time, что-ли. Следующий код тоже не будет работать, так что сама реализация bar тут абсолютно не причем (ведь работает другой, точно такой-же foo, не являющийся, правда, методом класса):
cdef void bar():
cdef void* b
b = foo()
b = A().foo()
Результат:
Error converting Pyrex file to C:
------------------------------------------------------------
...

cdef void bar():
cdef void* b
b = foo()
b = A().foo()
^
------------------------------------------------------------

./test.pyx:20:12: Cannot convert Python object to 'void *'
..bw
alex000090
Здравствуйте! Я не особо хорошо владею C и Pyrex, но все же попробую помочь:

Что касается этого:
<code>
cdef void bar(object a):
cdef void* b
b = foo()
b = a.foo()
</code>
Вы передаете Python объект a => a.foo() - Член-функция Python объекта => возвращает только Python объект! Ошибка естественна.

Далее:
<code>
cdef void bar():
cdef void* b
b = foo()
b = A().foo()
</code>
Первое замечание: Pyrex это компилирует, Cython выдает все туже ошибку.
Второе замечание: b - переменная одного из типов C, а в C не существует вызова класса. Нужно создать объект данного типа!
Исправление:
<code>
cdef void bar():
cdef void* b
cdef A a
b = foo()
b = a.foo()
</code>
Компиляция проходит и у Pyrex и у Cython.

Удачи!

Платформа: Gentoo Linux 2008 x86_64
Компилятор: gcc 4.1.2
Pyrex version 0.9.8.5
Cython version 0.9.8.1.1
bw
Любопытно. Спасибо. Думаю, что теперь понял, в чем дело и как следовало поступить. Хотя задача сейчас не актуальна, я все же время от времени возвращаюсь к Pyrex/Cython, а значит и к этой проблеме. Еще раз спасибо за помощь.

..bw
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB