Far from a c expert but for me using ubuntu, the following works:

main.c:

#include "foo_api.h"
#include <stdio.h>


int main(int argc, char *argv[]) {
     Py_Initialize();
     initfoo();
     import_foo();
     double arr[5] = {1,2,3,4,5};
     int i = 0;
     foo(arr);
     for(i = 0; i < 5; i++)
    {
      printf("%f\n", arr[i]);
    }
     Py_Finalize();
     return 0;
}

foo.pyx:

cdef public api  foo(double* x):
   x[0] = 0.0

From the same directory:

$ cython foo.pyx 

Then:

$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o foo  *.c -lpython2.7 

Then just run.

$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000

I used pkg-config --cflags python to get the flags:

 $ pkg-config --cflags python
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 

Without calling Py_Initialize (Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions;), you will get:

Fatal Python error: PyThreadState_Get: no current thread
Aborted (core dumped)

Without initfoo() or import_foo() you get a:

 Segmentation fault (core dumped)

If you don't call Py_Finalize:

Py_Initialize a no-op when called for a second time (without calling Py_Finalize() first).

To get the delorean example from the docs to run:

main.py:

#include "delorean_api.h"
#include <stdio.h>
Vehicle car;


int main(int argc, char *argv[]) {
     Py_Initialize();
     initdelorean();
     import_delorean();
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     activate(&car);
     Py_Finalize();
     return 0;
}

delorean.pyx:

ctypedef public struct Vehicle:
    int speed
    float power

cdef api void activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        print "Time travel achieved"
    else:
        print("Sorry Marty")

The procedure is the same, the only change was I had to use ctypedef with the Vehicle struct or else in main or use I had t use struct Vehicle car; in main:

$ cython delorean.pyx
$ cc  -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o delorean  *.c -lpython2.7  
$ ./delorean 1 1
Sorry Marty
$ ./delorean 100 2
Time travel achieved

You can also get it to work without using Py_Initialize etc...

In foo.pyx you just need to make the function public:

cdef public  foo(double* x):
   x[0] = 0.0

I added #include <python2.7/Python.h> just imported foo.hin main.c and removed Py_Initialize(); etc. Just importing python.h would not work for me but that may not be the case for everyone.

#include <python2.7/Python.h>
#include "foo.h"
#include <stdio.h>


int main(int argc, char *argv[]) {
     double arr[5] = {1,2,3,4,5};
     int i = 0;
     foo(arr);
     for(i = 0; i < 5; i++)
    {
      printf("%f\n", arr[i]);
    }

     return 0;
}

Compiling was the same:

$ cython foo.pyx 
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o foo  *.c -lpython2.7 
$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000

If you are using the api version then just include the api header or vice versa as per the docs However, note that you should include either modulename.h or modulename_api.h in a given C file, not both, otherwise you may get conflicting dual definitions.

To do the same with the delorean example I had to use libc.stdio to print the strings to avoid a segmentation fault:

from libc.stdio cimport printf

ctypedef public  struct Vehicle:
    int speed
    float power

cdef public void activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        printf("Time travel achieved\n")
    else:
        printf("Sorry Marty\n")

main:

#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"

Vehicle car;


int main(int argc, char *argv[]) {
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     activate(&car);
     return 0;
}

It might make more sense to return the values:

ctypedef public  struct Vehicle:
    int speed
    float power

cdef public  char* activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        return  "Time travel achieved"
    return "Sorry Marty"

main:

#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"

Vehicle car;

int main(int argc, char *argv[]) {
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     printf("%s\n",activate(&car));
     return 0;
}
Answer from Padraic Cunningham on Stack Overflow
🌐
GitHub
github.com › cython › cython
GitHub - cython/cython: The most widely used Python to C compiler · GitHub
Nuitka, a static Python-to-C extension compiler. Pros: highly language compliant, reasonable performance gains, support for static application linking (similar to cython_freeze but with the ability to bundle library dependencies into a self-contained executable)
Starred by 10.7K users
Forked by 1.6K users
Languages   Cython 51.6% | Python 41.9% | C 6.2% | C++ 0.2% | Shell 0.1% | Starlark 0.0%
🌐
Cython
cython.readthedocs.io › en › latest › src › tutorial › cython_tutorial.html
Basic Tutorial — Cython 3.3.0a0 documentation
The fundamental nature of Cython can be summed up as follows: Cython is Python with C data types. Cython is Python: Almost any piece of Python code is also valid Cython code. (There are a few Limitations, but this approximation will serve for now.) The Cython compiler will convert it into C code ...
Top answer
1 of 1
15

Far from a c expert but for me using ubuntu, the following works:

main.c:

#include "foo_api.h"
#include <stdio.h>


int main(int argc, char *argv[]) {
     Py_Initialize();
     initfoo();
     import_foo();
     double arr[5] = {1,2,3,4,5};
     int i = 0;
     foo(arr);
     for(i = 0; i < 5; i++)
    {
      printf("%f\n", arr[i]);
    }
     Py_Finalize();
     return 0;
}

foo.pyx:

cdef public api  foo(double* x):
   x[0] = 0.0

From the same directory:

$ cython foo.pyx 

Then:

$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o foo  *.c -lpython2.7 

Then just run.

$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000

I used pkg-config --cflags python to get the flags:

 $ pkg-config --cflags python
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 

Without calling Py_Initialize (Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions;), you will get:

Fatal Python error: PyThreadState_Get: no current thread
Aborted (core dumped)

Without initfoo() or import_foo() you get a:

 Segmentation fault (core dumped)

If you don't call Py_Finalize:

Py_Initialize a no-op when called for a second time (without calling Py_Finalize() first).

To get the delorean example from the docs to run:

main.py:

#include "delorean_api.h"
#include <stdio.h>
Vehicle car;


int main(int argc, char *argv[]) {
     Py_Initialize();
     initdelorean();
     import_delorean();
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     activate(&car);
     Py_Finalize();
     return 0;
}

delorean.pyx:

ctypedef public struct Vehicle:
    int speed
    float power

cdef api void activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        print "Time travel achieved"
    else:
        print("Sorry Marty")

The procedure is the same, the only change was I had to use ctypedef with the Vehicle struct or else in main or use I had t use struct Vehicle car; in main:

$ cython delorean.pyx
$ cc  -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o delorean  *.c -lpython2.7  
$ ./delorean 1 1
Sorry Marty
$ ./delorean 100 2
Time travel achieved

You can also get it to work without using Py_Initialize etc...

In foo.pyx you just need to make the function public:

cdef public  foo(double* x):
   x[0] = 0.0

I added #include <python2.7/Python.h> just imported foo.hin main.c and removed Py_Initialize(); etc. Just importing python.h would not work for me but that may not be the case for everyone.

#include <python2.7/Python.h>
#include "foo.h"
#include <stdio.h>


int main(int argc, char *argv[]) {
     double arr[5] = {1,2,3,4,5};
     int i = 0;
     foo(arr);
     for(i = 0; i < 5; i++)
    {
      printf("%f\n", arr[i]);
    }

     return 0;
}

Compiling was the same:

$ cython foo.pyx 
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7   -o foo  *.c -lpython2.7 
$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000

If you are using the api version then just include the api header or vice versa as per the docs However, note that you should include either modulename.h or modulename_api.h in a given C file, not both, otherwise you may get conflicting dual definitions.

To do the same with the delorean example I had to use libc.stdio to print the strings to avoid a segmentation fault:

from libc.stdio cimport printf

ctypedef public  struct Vehicle:
    int speed
    float power

cdef public void activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        printf("Time travel achieved\n")
    else:
        printf("Sorry Marty\n")

main:

#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"

Vehicle car;


int main(int argc, char *argv[]) {
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     activate(&car);
     return 0;
}

It might make more sense to return the values:

ctypedef public  struct Vehicle:
    int speed
    float power

cdef public  char* activate(Vehicle *v):
    if v.speed >= 88 and v.power >= 1.21:
        return  "Time travel achieved"
    return "Sorry Marty"

main:

#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"

Vehicle car;

int main(int argc, char *argv[]) {
     car.speed = atoi(argv[1]);
     car.power = atof(argv[2]);
     printf("%s\n",activate(&car));
     return 0;
}
🌐
GitHub
gist.github.com › vi4hu › a1aae1a6d209705a14bca2b7c4c7625e
Convert and Compile python in c via cython · GitHub
Convert and Compile python in c via cython. GitHub Gist: instantly share code, notes, and snippets.
🌐
Opensource.com
opensource.com › article › 21 › 4 › cython
Optimize your Python code with C | Opensource.com
April 26, 2021 - CC BY-SA 4.0 · Cython is a compiler ... is also a superset of the Python language, and it supports calling C functions and declaring C types on variables and class attributes....
🌐
YouTube
youtube.com › watch
Cython 3.0: Compiling Python to C, the next generation - YouTube
The Cython project compiles Python to C -- not just to make code faster, but also to wrap external C libraries easily, and make it easy to write C extensions...
Published   July 25, 2023
🌐
Arch Linux Forums
bbs.archlinux.org › viewtopic.php
Converting Python To C with Cython / Programming & Scripting / Arch Linux Forums
Fix the Include in your Cython converted C-File, like this: #include "python2.7/Python.h" instead of #include "Python.h".
Find elsewhere
🌐
Quora
quora.com › I-want-to-convert-my-Python-code-to-C-with-Cython-and-then-compile-it-to-exe-for-Windows-64-bit-How-can-I-do-that
I want to convert my Python code to C with Cython and then compile it to .exe for Windows 64 bit. How can I do that? - Quora
Answer: You can follow the below steps - 1. As Cython can accept only valid python source file so first make sure that your python code is working without any error/issue. 2. Give a file name extension as .pyx instead of .py extension. 3. Then you can write a Setup.py file for Cython. A basic cy...
🌐
Machine Learning Plus
machinelearningplus.com › blog › how to convert python code to cython (and speed up 100x)?
How to convert Python code to Cython (and speed up 100x)? | machinelearningplus
October 17, 2023 - Using Cython, you can speed up existing Python code by an order of 100x or more. This is possible because Cython converts some of the Python code to C by doing some basic code changes.
🌐
GitHub
hplgit.github.io › primer.html › doc › pub › cython › cython-readable.html
Migrating Python to compiled code
August 13, 2020 - Pure Python code for Monte Carlo simulation · The computational problem · A scalar Python implementation · A vectorized Python implementation · Migrating scalar Python code to Cython · A plain Cython implementation · A better Cython implementation · Migrating code to C ·
🌐
InfoWorld
infoworld.com › home › software development › programming languages › python
What is Cython? Python at the speed of C | InfoWorld
June 1, 2023 - If you feed the Cython compiler a Python program (Python 2.x and Python 3.x are both supported), Cython will accept it as-is, but none of Cython’s native accelerations will come into play. But if you decorate the Python code with type annotations in Cython’s special syntax, Cython will be able to substitute fast C equivalents for slow Python objects.
Top answer
1 of 4
8

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 of 4
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.

🌐
GitHub
github.com › Pranjalab › pyencrypt
GitHub - Pranjalab/pyencrypt: Converting python files to cython files · GitHub
In this Project, we will convert a .py file to .pyd file using cython to encrypt our code or to increase the speed of our algorithm. In this Project, we will convert a .py file to .pyd or .c file, where .pyd is kind of a .dll file for python which can be called in any python script but its ...
Starred by 25 users
Forked by 4 users
Languages   Python
🌐
FutureLearn
futurelearn.com › home › blog
Interfacing C code with Cython
October 25, 2022 - In order to use C functions and variables from the library, one must provide external declarations for them in the Cython .pyx file. While normal cdef declarations refer to functions and variables that are defined in the same file, by adding ...
🌐
Paperspace
blog.paperspace.com › boosting-python-scripts-cython
Boosting Python Scripts With Cython | DigitalOcean
May 2, 2025 - In this article, we’ll explore how you can use Cython to supercharge your Python code by converting it into fast, compiled C code—without leaving the comfort of Python syntax.
🌐
Towards Data Science
towardsdatascience.com › home › latest › cython for absolute beginners: 30x faster code in two simple steps
Cython for absolute beginners: 30x faster code in two simple steps | Towards Data Science
March 5, 2025 - Combine the ease and speed of ... We do this by using a package called Cython that will convert our Python-code to a compiled, superfast piece of C-code that we can directly import into our project again....
🌐
Medium
medium.com › @v1per › cython-use-c-c-functions-in-python-fcb91dae8533
Cython — use C/C++ functions in Python | by Himanshu Das | Medium
September 17, 2023 - Cython is based on Pyrex, but supports more cutting edge functionality and optimizations. Cython translates Python code to C/C++ code, but additionally supports calling C functions and declaring C types on variables and class attributes.
🌐
Brainly
brainly.in › computer science › secondary school
convert python code to c - Brainly.in
January 12, 2023 - %%cython -a cpdef double cy_fib(int n): cdef double a, b a = 0 b = 1 for i in range(n): a, b = a+b, a return a.