5

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:

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.

  • 3
    install [python-dev](http://packages.ubuntu.com/search?keywords=python-dev) – Noelkd Apr 04 '16 at 09:39
  • 3
    The accepted answer to your first example question - did you try instead doing `sudo apt-get install python3-dev`? (note the 3). On 14.04, you need to do that to get the dev libraries for py 3 instead of 2. – J Richard Snape Apr 04 '16 at 09:40
  • 1
    @JRichardSnape Yes I'm sure that I have changed all the python version where necessary, but I will try again. –  Apr 04 '16 at 09:41
  • 1
    Note also - you might need to do the minor version specific command e.g. `install python3.4-dev` – J Richard Snape Apr 04 '16 at 09:42
  • 1
    @JRichardSnape I've done both of that but still the same error :( –  Apr 04 '16 at 09:43
  • 1
    @Noelkd I have installed `python-dev` and `python3-dev` but they are both the newest version. –  Apr 04 '16 at 09:44
  • 2
    You need to tell gcc where the headers are (e.g. pass the path with `-I` to the compiler or `-l` for libraries when linking. – J Richard Snape Apr 04 '16 at 10:09

3 Answers3

7

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.

viraptor
  • 33,322
  • 10
  • 107
  • 191
  • 1
    I am using this command: `gcc -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing /usr/include/python3.4 -o test.so test.c` but I still get the error. –  Apr 04 '16 at 10:19
  • 1
    If you get the same error, then check which version of headers you actually have installed. Or you can avoid all specifics by just compiling with `gcc $(pkg-config --libs --cflags python3) greet.c -o greet`. If you get an error about missing `main` instead, you need to use `cython3 --embed greet.py`. – viraptor Apr 04 '16 at 10:27
  • 1
    Your instructions have gotten rid of all the other errors but one remains `Must specify package names on the command line.` and then it says `pyconfig.h no such file or directory`. –  Apr 04 '16 at 10:39
  • 1
    That's OK we all make mistakes. I have used the updated instructions and I now have a couple dozen `undefined reference to` errors does this mean that there is a error in my source code? –  Apr 04 '16 at 10:45
  • 1
    What's the undefined name? Can you paste the error? – viraptor Apr 04 '16 at 10:47
  • 1
    All of the names beginning with`Py|_PY` are `undefined`. –  Apr 04 '16 at 10:49
  • 1
    I give up. `--libs` option should've sorted that problem out. I get the same errors without it. If you run `pkg-config --libs --cflags python3`, you should get back something like `-I/usr/include/python3.5m -lpython3.5m`. If you don't, something's very wrong and you should debug that :) – viraptor Apr 04 '16 at 10:55
  • 1
    I GOT IT TO COMPILE! The `--shared` option is what compiled it, I compiled it into a .so file but when I run it I get the error `segmentation fault (core dumped)` –  Apr 04 '16 at 10:59
  • I can replicate your error. Strip back the adding of the includes and libraries via `pkg-config` and try : `snapey@snapey-VirtualBox:~$ gcc -I/usr/include/python3.4m -o greet greet.c -lpython3.4m` Just this works for me. You probably do need the `--embed` in the `cython3` call. I don't know why the evaluating of `pkg-config` doesn't work - it seems to have to do with it adding `-I/usr/include/x86_64-linux-gnu/python3.4m` to the includes as well as `-I/usr/include/python3.4m` - maybe some conflicts...? – J Richard Snape Apr 04 '16 at 13:47
  • Unfortunately when you compile `-shared -fPIC` you're just defering all those "unresolved name" errors from compile to runtime. What you could do is try to move pkgconfig part to the end of the commandline. Older gcc may be funny about the options order. – viraptor Apr 05 '16 at 01:39
  • @viraptor great answer. I have a small question though. Is the resulting exe portable (are the libraries static or dynamic linked). I tried using `- static`, in an attempt to ensure this, unfortunately `gcc` failed to compile with the message that `python3.4m` can't be found. Compiling using the options described in your answer only, works splendid though. – Alexander Cska Dec 07 '17 at 12:53
  • In my environment, the example `gcc $(pkg-config --libs --cflags python3) greet.c -o greet` does not work (it gives many undefined symbols in link) because the .c file comes after the libraries emitted by pkg-config. Simply listing the .c file earlier, such as `gcc greet.c $(pkg-config --libs --cflags python3) -o greet` works fine! – rpdrewes Oct 23 '18 at 17:37
0

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.

Community
  • 1
  • 1
J Richard Snape
  • 20,116
  • 5
  • 51
  • 79
  • I have a bunch of `Python.h`'s, one for each Conda env, for Pycharm, for vscode, etc. Some of them are small case `python.h`. I should probably try the one in the activated conda env. – mLstudent33 Oct 31 '19 at 00:33
-2

Python 2:

python -m pip install --upgrade cython

Python 3:

python3 -m pip install --upgrade cython
myworldbox
  • 361
  • 6
  • 11
  • That looks like how you update Cython. However, the question was asking how to compile Cython-generated C files – DavidW Feb 23 '22 at 20:16
  • If you have actually tested, the issues are solved exactly by using my approach. – myworldbox Feb 24 '22 at 03:45
  • Maybe you should explain why. Because it looks like the person asking the question already has an up-to-date version of Cython installed. The accepted answer shows that the problem was the include path passed to gcc – DavidW Feb 25 '22 at 10:07