Функция Cython Extern C

#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 на внешней части и все еще получаю ту же ошибку, я что-то упускаю?