How to use Cython to compile Python 3 into C

2019-04-12 21:31发布

问题:

I'm trying to convert a Python 3 script into C and then compile that C file into an executable.

I have this simple python script:

def greet(name = ""):
  print("Hello {0}".format(name if len(name) > 0 else "World"))

greet("Mango")

I've converted this script into C using:

cython greet.py -o greet.c

Then I've compiled the C file using:

cc greet.c -o greet

After I entered the last command I got the error:

fatal error: Python.h: No such file or directory compilation terminated.

After I got the error I went back and realised that I was using Python3 and that I had forgot the "3" after "cython".
So re-compiled the python script using:

cython3 greet.py -o greet.c

Then attempted to re-compile the C file using:

cc greet.c -o greet

Again this failed and threw the same error so I went searching on SO and Google and found these questions:

  • fatal error: Python.h: No such file or directory
  • I have Python on my Ubuntu system, but gcc can't find Python.h
  • https://askubuntu.com/questions/526708/fatal-error-python-h-no-file-or-directory

None of these answers in these questions work.

I've made sure that I have installed cython all of the correct dependencies using apt-get install and pip install sadly thought it still does not seem to work.

回答1:

Check the documentation. It's not enough to do gcc x.c -o x.

This page explains compilation: http://docs.cython.org/src/reference/compilation.html

There's a lot more to it, but a direct answer is:

Compiling your .c files will vary depending on your operating system. Python documentation for writing extension modules should have some details for your system. Here we give an example on a Linux system:

$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.7 -o yourmod.so yourmod.c

Of course in your situation it's going to be something closer to -I/usr/include/python3.4, or even $(pkg-config --libs --cflags python3). And you're not building with -shared, because you want an executable.

Shortest "this has to work" set of commands is:

cython3 --embed greet.py -o greet.c
gcc $(pkg-config --libs --cflags python3) greet.c -o greet

You need to install pkg-config if it's missing.



回答2:

As @viraptor's answer shows you and as per my comment, your main problem is that you need to tell your C compiler (e.g. gcc) where to find the python headers required (pyconfig.h and Python.h). To do this, you need to pass a -I option to gcc.

The other answer suggests using pkg-config to add this to your command line. However, like you, with Ubuntu 14.04, cython3 and python3-dev installs, using this method leads the compiled program to exit with a segmentation fault for me.

So, I suggest you go back to basics. After

cython greet.py -o greet.c

Run the following command. It assumes that Python.h and friends are in the standard place (i.e. you've done a standard install of python3-dev)

gcc -I/usr/include/python3.4m -o greet greet.c -lpython3.4m

If that doesn't work - use find / -iname Python.h to find the location of the necessary files and alter the -I path accordingly.

In time, when you want to use cython on more complex programs, such as those that link to other C libraries, you'll need to learn about the other options you need to pass to gcc to get it to compile and link correctly. To get you going, though, the above should work (tested on Ubuntu 14.04 as per your spec)

P.S. I'm not sure why the pkg-config suggestion doesn't work - but for me it seems to add in an extra path to -I which breaks things.