简单的 Cython 文件在使用 cpdef 时导致重定义错误
Simple Cython file causes redefinition errors when using cpdef
我有一个简单的 cython *.pyx 文件导致了一堆重定义错误,我不明白为什么。如果我将 'cpdef' 更改为 'cdef' 它编译正常,但不会导出这些函数,我希望它们被导出。有人可以解释为什么会失败,或者我在这里做错了什么吗?
core.pyx:
cdef extern from "module.h":
cpdef double radians(double degrees)
cpdef double degrees(double radians)
module.h:
#ifndef MODULE_H
#define MODULE_H
double radians(double degrees);
double degrees(double radians);
#endif
module.c:
#include "module.h"
double radians(double degrees)
{
return degrees * (M_PI / 180.0);
}
double degrees(double radians)
{
return radians * (180.0 / M_PI);
}
错误:
$ python3 setup.py build
running build
running build_ext
building 'core' extension
x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -Iinclude -I/usr/include/python3.8 -c src/core.c -o build/temp.linux-x86_64-3.8/src/core.o
src/core.c:1294:13: error: redefinition of ‘__pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’
1294 | static char __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap[] = "wrap(radians: float) -> float";
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1146:13: note: previous definition of ‘__pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’ was here
1146 | static char __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap[] = "wrap(degrees: float) -> float";
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1295:20: error: redefinition of ‘__pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’
1295 | static PyMethodDef __pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap = {"wrap", (PyCFunction)__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap, METH_O, __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1147:20: note: previous definition of ‘__pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’ was here
1147 | static PyMethodDef __pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap = {"wrap", (PyCFunction)__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap, METH_O, __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1296:18: error: redefinition of ‘__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’
1296 | static PyObject *__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap(PyObject *__pyx_self, PyObject *__pyx_arg_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1148:18: note: previous definition of ‘__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’ was here
1148 | static PyObject *__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap(PyObject *__pyx_self, PyObject *__pyx_arg_degrees) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1317:18: error: redefinition of ‘__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’
1317 | static PyObject *__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap(PyObject *__pyx_self, double __pyx_v_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1169:18: note: previous definition of ‘__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’ was here
1169 | static PyObject *__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap(PyObject *__pyx_self, double __pyx_v_degrees) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1370:18: error: redefinition of ‘__Pyx_CFunc_double____double___to_py’
1370 | static PyObject *__Pyx_CFunc_double____double___to_py(double (*__pyx_v_f)(double)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1222:18: note: previous definition of ‘__Pyx_CFunc_double____double___to_py’ was here
1222 | static PyObject *__Pyx_CFunc_double____double___to_py(double (*__pyx_v_f)(double)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1317:18: warning: ‘__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’ defined but not used [-Wunused-function]
1317 | static PyObject *__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap(PyObject *__pyx_self, double __pyx_v_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1296:18: warning: ‘__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’ defined but not used [-Wunused-function]
1296 | static PyObject *__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap(PyObject *__pyx_self, PyObject *__pyx_arg_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1222:18: warning: ‘__Pyx_CFunc_double____double___to_py’ defined but not used [-Wunused-function]
1222 | static PyObject *__Pyx_CFunc_double____double___to_py(double (*__pyx_v_f)(double)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
正如 DavidW 所指出的,这可能是一个错误。看起来,在生成的 C 代码中使用的变量名只采用变量类型而不是函数的名称,因此 __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap
被定义了两次:一次是 radians
一次是 degrees
.
因此您暂时应该使用变通方法。一种是给双打不同的名字,例如:
%%cython -a --verbose
cdef extern from *:
"""
//some dummy implementations
double radians(double degrees)
{
return degrees * (1.0 / 180.0);
}
int degrees(double radians)
{
return radians * (180.0 / 1.0);
}
"""
ctypedef double double1 "double"
cpdef double degrees(double radians)
cpdef double1 radians(double degrees)
这里我们使用 cname
技巧,Cython 将用“double”替换“double1”。
但这看起来不像是更大 scale/long 术语的理智解决方案。我会切换到更冗长但不那么令人费解的方法(假设在 extern (here documentation) 中使用 cpdef
无论如何都不是很常见):
%%cython -a
cdef extern from *:
"""
// code as above
...
"""
double c_degrees "degrees"(double radians)
double c_radians "radians"(double degrees)
cpdef double degrees(double radians):
return c_degrees(radians)
cpdef double radians(double degrees):
return c_radians(degrees)
再一次,cname
-trick 用于区分 cpdef
和 Cython 代码中函数的 wrappend cname。
我有一个简单的 cython *.pyx 文件导致了一堆重定义错误,我不明白为什么。如果我将 'cpdef' 更改为 'cdef' 它编译正常,但不会导出这些函数,我希望它们被导出。有人可以解释为什么会失败,或者我在这里做错了什么吗?
core.pyx:
cdef extern from "module.h":
cpdef double radians(double degrees)
cpdef double degrees(double radians)
module.h:
#ifndef MODULE_H
#define MODULE_H
double radians(double degrees);
double degrees(double radians);
#endif
module.c:
#include "module.h"
double radians(double degrees)
{
return degrees * (M_PI / 180.0);
}
double degrees(double radians)
{
return radians * (180.0 / M_PI);
}
错误:
$ python3 setup.py build
running build
running build_ext
building 'core' extension
x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -Iinclude -I/usr/include/python3.8 -c src/core.c -o build/temp.linux-x86_64-3.8/src/core.o
src/core.c:1294:13: error: redefinition of ‘__pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’
1294 | static char __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap[] = "wrap(radians: float) -> float";
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1146:13: note: previous definition of ‘__pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’ was here
1146 | static char __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap[] = "wrap(degrees: float) -> float";
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1295:20: error: redefinition of ‘__pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’
1295 | static PyMethodDef __pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap = {"wrap", (PyCFunction)__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap, METH_O, __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1147:20: note: previous definition of ‘__pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’ was here
1147 | static PyMethodDef __pyx_mdef_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap = {"wrap", (PyCFunction)__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap, METH_O, __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1296:18: error: redefinition of ‘__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’
1296 | static PyObject *__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap(PyObject *__pyx_self, PyObject *__pyx_arg_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1148:18: note: previous definition of ‘__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’ was here
1148 | static PyObject *__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap(PyObject *__pyx_self, PyObject *__pyx_arg_degrees) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1317:18: error: redefinition of ‘__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’
1317 | static PyObject *__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap(PyObject *__pyx_self, double __pyx_v_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1169:18: note: previous definition of ‘__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’ was here
1169 | static PyObject *__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap(PyObject *__pyx_self, double __pyx_v_degrees) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1370:18: error: redefinition of ‘__Pyx_CFunc_double____double___to_py’
1370 | static PyObject *__Pyx_CFunc_double____double___to_py(double (*__pyx_v_f)(double)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1222:18: note: previous definition of ‘__Pyx_CFunc_double____double___to_py’ was here
1222 | static PyObject *__Pyx_CFunc_double____double___to_py(double (*__pyx_v_f)(double)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1317:18: warning: ‘__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap’ defined but not used [-Wunused-function]
1317 | static PyObject *__pyx_pf_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap(PyObject *__pyx_self, double __pyx_v_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1296:18: warning: ‘__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap’ defined but not used [-Wunused-function]
1296 | static PyObject *__pyx_pw_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_1wrap(PyObject *__pyx_self, PyObject *__pyx_arg_radians) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core.c:1222:18: warning: ‘__Pyx_CFunc_double____double___to_py’ defined but not used [-Wunused-function]
1222 | static PyObject *__Pyx_CFunc_double____double___to_py(double (*__pyx_v_f)(double)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
正如 DavidW 所指出的,这可能是一个错误。看起来,在生成的 C 代码中使用的变量名只采用变量类型而不是函数的名称,因此 __pyx_doc_11cfunc_dot_to_py_36__Pyx_CFunc_double____double___to_py_wrap
被定义了两次:一次是 radians
一次是 degrees
.
因此您暂时应该使用变通方法。一种是给双打不同的名字,例如:
%%cython -a --verbose
cdef extern from *:
"""
//some dummy implementations
double radians(double degrees)
{
return degrees * (1.0 / 180.0);
}
int degrees(double radians)
{
return radians * (180.0 / 1.0);
}
"""
ctypedef double double1 "double"
cpdef double degrees(double radians)
cpdef double1 radians(double degrees)
这里我们使用 cname
技巧,Cython 将用“double”替换“double1”。
但这看起来不像是更大 scale/long 术语的理智解决方案。我会切换到更冗长但不那么令人费解的方法(假设在 extern (here documentation) 中使用 cpdef
无论如何都不是很常见):
%%cython -a
cdef extern from *:
"""
// code as above
...
"""
double c_degrees "degrees"(double radians)
double c_radians "radians"(double degrees)
cpdef double degrees(double radians):
return c_degrees(radians)
cpdef double radians(double degrees):
return c_radians(degrees)
再一次,cname
-trick 用于区分 cpdef
和 Cython 代码中函数的 wrappend cname。