简体   繁体   中英

Point Cython to C source files

I have a project mixing Python, Cython and C arranged like so:

root
    |- src
        |- foo
            foo.c
    |- name
        name.pxd
        name.pyx
    |- include
        |- foo
            foo.h
    setup.py

with very simple contents:

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"])
)

And compile with the following command:

CFLAGS="-I/path/to/root/include" python setup.py build_ext -i

Which compiles fine, except when I try import name in the python interpreter I get the following:

ImportError: dlopen(./name.so, 2): Symbol not found: _add
  Referenced from: ./name.so
  Expected in: dynamic lookup

which I assume means that even though everything compiled, Cython is not actually linking the right files together. What am I missing?

Turns out I had to change two things. I forgot to tell name.pyx to import name.pxd . So I had to add this line to the top of name.pyx :

from name cimport add

It also worked when I included distutils header information in name.pyx itself, so put these lines at the very top of name.pyx :

#distutils: language = c
#distutils: sources = src/foo/foo.c

And changed setup.py like so:

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)
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM