我有一个混合Python,Cython和C的项目,如下所示:
root
|- src
|- foo
foo.c
|- name
name.pxd
name.pyx
|- include
|- foo
foo.h
setup.py
内容非常简单:
foo.h中:
void add(int, double *, double *, double *);
foo.c的:
#include "foo/foo.h"
void add(int N, double * A, double * B, double * C) {
for (int i = 0; i < N; i++) C[i] = A[i]+B[i];
}
name.pxd:
cdef extern from "foo/foo.h":
void add(int, double *, double *, double *)
name.pyx:
import numpy as np
cimport numpy as np
cpdef cython_add(np.ndarray[np.double_t, ndim=1] A,
np.ndarray[np.double_t, ndim=1] B):
cdef int N = min(A.shape[0], B.shape[0])
cdef np.ndarray C = np.ndarray([N],dtype=np.double)
add(N, <double*> A.data, <double*> B.data, <double*> C.data)
return C
setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("name/*.pyx", sources=["src/foo/foo.c"])
)
使用以下命令编译:
CFLAGS="-I/path/to/root/include" python setup.py build_ext -i
哪个编译好,除非我在python解释器中尝试import name
,我得到以下内容:
ImportError: dlopen(./name.so, 2): Symbol not found: _add
Referenced from: ./name.so
Expected in: dynamic lookup
我认为这意味着即使编译了所有内容,Cython实际上并没有将正确的文件链接在一起。我错过了什么?
答案 0 :(得分:0)
原来我必须改变两件事。我忘了告诉name.pyx
导入name.pxd
。所以我必须将此行添加到name.pyx
的顶部:
from name cimport add
当我在distutils
本身中包含name.pyx
标题信息时,它也有效,因此请将这些行放在name.pyx
的最顶部:
#distutils: language = c
#distutils: sources = src/foo/foo.c
并改变了setup.py
,如此:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
from numpy import get_include
extensions = [
Extension("name", ["name/name.pyx"],
include_dirs = ["include", get_include()])
]
setup(
name = "name",
ext_modules = cythonize(extensions)
)