#cython
#цитон
Вопрос:
Я пытаюсь передать функцию c в cython. Вот мой код (все файлы находятся в одном каталоге)
function.cpp
int cfunc(int x){ return x; }
обертка.пикс
cdef extern from "function.cpp": cpdef int cfunc(int) def pyfunc(int x): return cfunc(x)
setup.py
from distutils.core import setup, Extension from Cython.Build import cythonize source = ['function.cpp', 'wrapper.pyx'] ext = [Extension('lib', source, language='c ')] setup(ext_modules=cythonize(ext))
Когда я запускаю python setup.py build_ext --inplace
, он выдает следующую ошибку
/home/hyunix/anaconda3/envs/c-playground/bin/../lib/gcc/x86_64-conda_cos6-linux-gnu/7.3.0/../../../../x86_64-conda_cos6-linux-gnu/bin/ld: build/temp.linux-x86_64-3.7/function.o: in function `cfunc(int)': function.cpp:(.text._Z5cfunci 0x0): multiple definition of `cfunc(int)'; build/temp.linux-x86_64-3.7/wrapper.o:wrapper.cpp:(.text._Z5cfunci 0x0): first defined here collect2: error: ld returned 1 exit status error: command '/home/hyunix/anaconda3/envs/c-playground/bin/x86_64-conda_cos6-linux-gnu-c ' failed with exit status 1
Однако, если я удалю language='c '
из setup.py это прекрасно работает. Почему это происходит?
Я использую:
- Python 3.7.9
- Цитон 0,29.21
- Ubuntu 20.04
Ответ №1:
Ну, когда вы используете cpdef int cfunc(int), вы явно создаете новую функцию C и новую функцию python. Если вы хотите ссылаться на cfunc (), как он определен извне в function.cpp, ваша подпись должна быть
cdef extern from "function.cpp": int cfunc(int)
Поэтому, когда вы компилируете с флагом language=’c ‘, Cython выдает вам соответствующую ошибку. Однако, когда вы удаляете флаг языка, Cython должен рассуждать на основе директив компилятора, запрашиваете ли вы .c или .cpp, и по умолчанию используется .c. Вы должны заметить, что ваша оболочка компилируется в .c вместо .cpp, когда аргумент языка удален. В этой компиляции C Cython не распознает подпись в файле .cpp, но распознает cpdef. Итак, ошибки нет, но вы получаете пустую функцию cfunc, в отличие от функции, определенной в cpp.
Комментарии:
1. Привет @Aitrean спасибо, что ответили. Я попытался скомпилировать без флага языка, и он действительно компилируется в оболочку (.c), как вы сказали, однако на самом деле он распознает функцию, определенную в файле (.cpp), и запускается должным образом. Я также попытался удалить cpdef на внешней части и все еще получаю ту же ошибку, я что-то упускаю?