Reputation: 13662
How do I compile using Cython, a C function from file simulate_fast.c
, where this also depends on further C files matrix.c
and random_generator.c
. This seems like it must be a common use of Cython but after reading through the documentation, I still cannot figure out how to do it. My directory contains the following files
matrix.c
matrix.h
random_generator.c
random_generator.h
simulate_fast.c
simulate_fast.h
test.c
simulate_fast_c.pyx
setup.py
The matrix.c
and random_generator.c
files contain standalone functionality. The simulate_fast.c
file uses both of these and contains the function I want to be exposed to Python, simulate()
.
The test.c
file tests that all the C functionality runs correctly i.e. I can execute
$ gcc test.c simulate_fast.c matrix.c random_generator.c -o test
to compile into a test
executable that works.
My issue now is trying to compile this with Cython. My .pyx
file is
cimport cython
cdef extern from "simulate_fast.h":
int simulate()
def simulate_cp():
return simulate()
I then use the basic setup.py
from distutils.core import setup
from Cython.Build import cythonize
from Cython.Distutils import build_ext
import numpy as np
setup(
name='simulate_fast',
ext_modules = cythonize(["simulate_fast_c.pyx"]),
include_dirs=[]
)
However if I try and compile this using
python3 setup.py build_ext --inplace
I get an error
In file included from simulate_fast_c.c:492:0:
simulate_fast.h:89:28: error: field ‘RG’ has incomplete type
struct RandomGenerator RG;
where structure RandomGenerator
is declared in random_generator.h
.
How do I tell the compiler we must also consider the matrix
and random_generator
files when compiling.
Update
If doing as ead
said in the comments, I include random_generator.h
and matrix.h
in simulate_fast.h
then the program now compiles. However when I try to import the simulate_fast_c
module in Python I get an ImportError
:
undefined symbol: simulate
Further, if I change the extern declaration line in simulate_fast.pyx
to
cdef extern from "simulate_fast.c":
int simulate()
I then get an import error
undefined symbol: get_random_number
which is a function in random_generator.h
Upvotes: 1
Views: 3033
Reputation: 7293
The cythonized module must either be linked to a shared library containing the compiled C code or embed it. One way to do the latter is to list the C sources as being an "Extension", then pass this extension to the cythonize command, as mentioned in Cython's documentation
The example setup.py
file in the link can be summarized by (modulo the imports):
setup(
ext_modules = cythonize(Extension("simulate_fast", ["matrix.c", "random_generator.c", "simulate_fast_c.pyx"]))
)
Upvotes: 1