You should call C from Python by writing a ctypes wrapper. Cython is for making python-like code run faster, ctypes is for making C functions callable from python. What you need to do is the following:

  1. Write the C functions you want to use. (You probably did this already)
  2. Create a shared object (.so, for linux, os x, etc) or dynamically loaded library (.dll, for windows) for those functions. (Maybe you already did this, too)
  3. Write the ctypes wrapper (It's easier than it sounds, I wrote a how-to for that)
  4. Call a function from that wrapper in Python. (This is just as simple as calling any other python function)
Answer from Florian Rhiem on Stack Overflow
Top answer
1 of 6
75

You should call C from Python by writing a ctypes wrapper. Cython is for making python-like code run faster, ctypes is for making C functions callable from python. What you need to do is the following:

  1. Write the C functions you want to use. (You probably did this already)
  2. Create a shared object (.so, for linux, os x, etc) or dynamically loaded library (.dll, for windows) for those functions. (Maybe you already did this, too)
  3. Write the ctypes wrapper (It's easier than it sounds, I wrote a how-to for that)
  4. Call a function from that wrapper in Python. (This is just as simple as calling any other python function)
2 of 6
9

If I understand well, you have no preference for dialoging as c => python or like python => c. In that case I would recommend Cython. It is quite open to many kinds of manipulation, specially, in your case, calling a function that has been written in Python from C.

Here is how it works (public api) :

The following example assumes that you have a Python Class (self is an instance of it), and that this class has a method (name method) you want to call on this class and deal with the result (here, a double) from C. This function, written in a Cython extension would help you to do this call.

cdef public api double cy_call_func_double(object self, char* method, bint *error):
    if (hasattr(self, method)):
        error[0] = 0
        return getattr(self, method)();
    else:
        error[0] = 1

On the C side, you'll then be able to perform the call like so :

PyObject *py_obj = ....
...
if (py_obj) {
    int error;
    double result;
    result = cy_call_func_double(py_obj, (char*)"initSimulation", &error);
    cout << "Do something with the result : " << result << endl;
}

Where PyObject is a struct provided by Python/C API After having caught the py_obj (by casting a regular python object, in your cython extension like this : <PyObject *>my_python_object), you would finally be able to call the initSimulation method on it and do something with the result. (Here a double, but Cython can deal easily with vectors, sets, ...)

Well, I am aware that what I just wrote can be confusing if you never wrote anything using Cython, but it aims to be a short demonstration of the numerous things it can do for you in term of merging.

By another hand, this approach can take more time than recoding your Python code into C, depending on the complexity of your algorithms. In my opinion, investing time into learning Cython is pertinent only if you plan to have this kind of needs quite often...

Hope this was at least informative...

🌐
Python
docs.python.org › 3 › extending › extending.html
1. Extending Python with C or C++ — Python 3.14.7 documentation
Let’s create an extension module called spam (the favorite food of Monty Python fans…) and let’s say we want to create a Python interface to the C library function system() [1]. This function takes a null-terminated character string as argument and returns an integer. We want this function to be callable from Python as follows:
Discussions

Calling C communication functions via Python?
Writing a c-extension for python is not as hard as it looks, the basics are: Setup the module properties using 'PyModuleDef' Setup the funcion properties using 'PyMethodDef' From your c-function deparse the python arguments, eg PyArg_ParseTuple When your ready to return a value package it up a python object Py_BuildValue There is nothing wrong with writing c-extensions for python, especially for interfaces you already have implemented in C. In fact someone once said that "c is syntactic sugar for memory and cpu", I'll add to that and say "python is syntacti sugar for c". ABelow is an annotated template I use when I need to interface with C. Build instructions at the end. This file a a compendium from sources like this and this #include /* Function 1: A simple 'hello world' The function needs to be static as its scope should be limited only to this file and it should return a PyObject exposed to our program via the Python.h header file. The wrapper function name will contain two arguments, both of type PyObject with the first being a pointer to self and the second a pointer to the args passed to the function via the calling Python code. */ static PyObject* helloworld(PyObject* self, PyObject* args) { printf("Hello World\n"); return Py_None; } /* Example 2: Fibonacci This function uses PyArgs_ParseTuple to unpack arguments, and Py_BuildValue to return python basic types. Both of these take argument specifiers: The below table shows what I feel are the more commonly used format specifiers. Specifier C Type Description ----------- ---------- --------------------------------------------- c char Python string of length 1 converted to C char s char array Python string converted to C char array d double Python float converted to a C double f float Python float converted to a C float i int Python int converted to a C int l long Python int converted to a C long o PyObject* Python object converted to a C PyObject How do arguments work? ---------------------- If you are passing multiple arguments to a function which are to be unpacked and coerced into C types, then you simply use multiple specifiers such as:: PyArg_ParseTuple(args, "si", &charVar, &intVar). How do return types work? ------------------------- Py_BuildValue uses format specifiers very similar to how PyArg_ParseTuple(...) uses them, just in the opposite direction. Py_BuildValue also allows for returning our familiar Python data structures such as tuples and dicts. In this wrapper function I will be returning an int to Python, which I implement as follows: Wrapper Code Returned to Python ----------------------------------------- ------------------ Py_BuildValue("s", "A") "A" Py_BuildValue("i", 10) 10 Py_BuildValue("(iii)", 1, 2, 3) (1, 2, 3) Py_BuildValue("{si,si}", "a', 4, "b", 9) {"a": 4, "b": 9} Py_BuildValue("") None */ int calc_fib(int n) { if(n < 2) { return n; } else { return calc_fib(n-1)+calc_fib(n-2); } } static PyObject* fib(PyObject* self, PyObject* args) { int n; if(!PyArg_ParseTuple(args, "i", &n)) return NULL; return Py_BuildValue("i", calc_fib(n)); } // Function table // -------------- // // Our Module's Function Definition struct. We require this `NULL` to signal // the end of our method definition. // // static PyMethodDef func_table[] = { { "helloworld", helloworld, METH_NOARGS, "Prints Hello World" }, { "fib", fib, METH_VARARGS, "Calculates fib number" }, { NULL, NULL, 0, NULL } }; // Our Module Definition // --------------------- // // Here I will provide a module definition which associates the previously // defined DemoLib_FunctionsTable array to the module. This struct is also // responsible for defining the name of the module that is exposed in Python // as well as giving a module-level doc string. static struct PyModuleDef myModule = { PyModuleDef_HEAD_INIT, "myModule", "Test Module", -1, func_table }; // Initializes our module using module struct // ------------------------------------------ // // The last C-ish bit of code to write is the module's initialization function, // which is the only non-static member of the wrapper code. This function has a // very particular naming convention of PyInit_name where name is the name of // the module. This function is invoked in the Python interpreter, which // creates the module and makes it accessible. PyMODINIT_FUNC PyInit_myModule(void) { return PyModule_Create(&myModule); } // Final Steps // ----------- // // Create a setup.py with the following code:: // // from distutils.core import setup, Extension // setup(name = 'myModule', version = '1.0', \ // ext_modules = [Extension('myModule', ['test.c'])]) // // And build and install with:: // // $ python setup.py build // $ python setup.py install // // No run with:: // // $ python // >>> import myModule // >>> myModule.fib(10) // 55 // // // More on reddit.com
🌐 r/C_Programming
6
10
September 20, 2018
How to call Python functions from C++, good description
Where do I find a good description of how to call Python functions from a C++ program ? More on learn.microsoft.com
🌐 learn.microsoft.com
2
0
August 14, 2025
Python libraries that use C: how do they work? I go the Python function definitions in the source code and they’re blank
Those definitions you're seeing are likely type hinting stubs - the actual code is in the C library, and the stubs are only used by your IDE to provide documentation and type signature information. More on reddit.com
🌐 r/learnpython
10
28
November 11, 2023
Calling Python from C++
Hi, as the title suggests, the question is whether there is a possibility to call a scripted python module from C++, and if yes, how to do that. More on discourse.slicer.org
🌐 discourse.slicer.org
9
0
August 1, 2019
🌐
Real Python
realpython.com › python-bindings-overview
Python Bindings: Calling C or C++ From Python – Real Python
March 18, 2026 - Are you a Python developer with a C or C++ library you’d like to use from Python? If so, then Python bindings allow you to call functions and pass data from Python to C or C++, letting you take advantage of the strengths of both languages.
🌐
Klein Embedded
kleinembedded.com › home › calling c code from python
Calling C code from Python - Klein Embedded
January 31, 2023 - You can try these out for yourself, but I am going to keep it simple and use the built-in ctypes package. The steps required for executing a C function in Python is as follows: Load a dynamic-link library (DLL) with the function you need. Specify the return type and the argument types.
🌐
Reddit
reddit.com › r/c_programming › calling c communication functions via python?
r/C_Programming on Reddit: Calling C communication functions via Python?
September 20, 2018 -

I'm trying to start some projects where I need to interface with some equipment via serial and IP comm protocols. I'd like to handle the direct communications part of this in C, which I know and love (and I can get some complete protocol stacks already done in C). However, I would much rather handle the user interface in Python. By user interface I mean everything from basic CLI testing tools for my own personal use, potentially progressing into a full GUI. Handling parsing etc is a breeze for me in Python, but I am more happy to do the meat in C.

My question is how best to do this in a non-dumb fashion, and without ruining the performance of the C part (or am I wasting time?).

From the what-Python-provides perspective, there seems to be the ctypes like route, the extension module route, and the Cython route. The ctypes/other wrappers route seems kind of chunky, and since I'm fine working in C I don't feel the need to hide it as quickly as possible. I started scratching the surface of the extension module route, it seems like something I can handle and what I'm leaning towards now. Cython feels like too much of a time investment.

Then I started thinking about just having the Python externally call a C program, and then that what I'm really thinking of is a client/server model where I want to interface with a C server, and I should go a sockets route or something, but then I forsee extra parsing overhead in C which defeats the whole point for me.

I understand that there's a host of problems regarding timing etc related to the fact this is networking, although I haven't thought all of these implications through yet. Common cases are going to be sniffing traffic, and low throughput writing of data. I'm thinking along the lines of using Python to display reads and initiate predefined network writes, more so than blasting out a continuous stream.

I guess this could be more of a Python question, but the general flavor of these questions when asked from the Python perspective is "I am using Python, how do I easily reuse this C code" whereas my current mindset is "I am using C, but want to farm out user-facing stuff to Python."

Some of my goals are related to professional pursuits, but the scope of this is really hobby grade (back office tool at best.) I'm a programmer by training but not by trade. There's probably a good chance this tack would increase complexity to the point of blowing away any time savings from the conveniences of Python.

Am I going to regret going the extension module route?

Top answer
1 of 3
6
Writing a c-extension for python is not as hard as it looks, the basics are: Setup the module properties using 'PyModuleDef' Setup the funcion properties using 'PyMethodDef' From your c-function deparse the python arguments, eg PyArg_ParseTuple When your ready to return a value package it up a python object Py_BuildValue There is nothing wrong with writing c-extensions for python, especially for interfaces you already have implemented in C. In fact someone once said that "c is syntactic sugar for memory and cpu", I'll add to that and say "python is syntacti sugar for c". ABelow is an annotated template I use when I need to interface with C. Build instructions at the end. This file a a compendium from sources like this and this #include /* Function 1: A simple 'hello world' The function needs to be static as its scope should be limited only to this file and it should return a PyObject exposed to our program via the Python.h header file. The wrapper function name will contain two arguments, both of type PyObject with the first being a pointer to self and the second a pointer to the args passed to the function via the calling Python code. */ static PyObject* helloworld(PyObject* self, PyObject* args) { printf("Hello World\n"); return Py_None; } /* Example 2: Fibonacci This function uses PyArgs_ParseTuple to unpack arguments, and Py_BuildValue to return python basic types. Both of these take argument specifiers: The below table shows what I feel are the more commonly used format specifiers. Specifier C Type Description ----------- ---------- --------------------------------------------- c char Python string of length 1 converted to C char s char array Python string converted to C char array d double Python float converted to a C double f float Python float converted to a C float i int Python int converted to a C int l long Python int converted to a C long o PyObject* Python object converted to a C PyObject How do arguments work? ---------------------- If you are passing multiple arguments to a function which are to be unpacked and coerced into C types, then you simply use multiple specifiers such as:: PyArg_ParseTuple(args, "si", &charVar, &intVar). How do return types work? ------------------------- Py_BuildValue uses format specifiers very similar to how PyArg_ParseTuple(...) uses them, just in the opposite direction. Py_BuildValue also allows for returning our familiar Python data structures such as tuples and dicts. In this wrapper function I will be returning an int to Python, which I implement as follows: Wrapper Code Returned to Python ----------------------------------------- ------------------ Py_BuildValue("s", "A") "A" Py_BuildValue("i", 10) 10 Py_BuildValue("(iii)", 1, 2, 3) (1, 2, 3) Py_BuildValue("{si,si}", "a', 4, "b", 9) {"a": 4, "b": 9} Py_BuildValue("") None */ int calc_fib(int n) { if(n < 2) { return n; } else { return calc_fib(n-1)+calc_fib(n-2); } } static PyObject* fib(PyObject* self, PyObject* args) { int n; if(!PyArg_ParseTuple(args, "i", &n)) return NULL; return Py_BuildValue("i", calc_fib(n)); } // Function table // -------------- // // Our Module's Function Definition struct. We require this `NULL` to signal // the end of our method definition. // // static PyMethodDef func_table[] = { { "helloworld", helloworld, METH_NOARGS, "Prints Hello World" }, { "fib", fib, METH_VARARGS, "Calculates fib number" }, { NULL, NULL, 0, NULL } }; // Our Module Definition // --------------------- // // Here I will provide a module definition which associates the previously // defined DemoLib_FunctionsTable array to the module. This struct is also // responsible for defining the name of the module that is exposed in Python // as well as giving a module-level doc string. static struct PyModuleDef myModule = { PyModuleDef_HEAD_INIT, "myModule", "Test Module", -1, func_table }; // Initializes our module using module struct // ------------------------------------------ // // The last C-ish bit of code to write is the module's initialization function, // which is the only non-static member of the wrapper code. This function has a // very particular naming convention of PyInit_name where name is the name of // the module. This function is invoked in the Python interpreter, which // creates the module and makes it accessible. PyMODINIT_FUNC PyInit_myModule(void) { return PyModule_Create(&myModule); } // Final Steps // ----------- // // Create a setup.py with the following code:: // // from distutils.core import setup, Extension // setup(name = 'myModule', version = '1.0', \ // ext_modules = [Extension('myModule', ['test.c'])]) // // And build and install with:: // // $ python setup.py build // $ python setup.py install // // No run with:: // // $ python // >>> import myModule // >>> myModule.fib(10) // 55 // // //
2 of 3
1
I built a program last year with a python front-end and a C backend. It communicates via TCP, which ended up working pretty nicely. The latency isn't very good, but it was good enough for a human-controlled GUI. the good thing about TCP is that nearly every language has an interface for this -- so you could rewrite your front end client in another language and not even have to touch the C portion.
🌐
Medium
medium.com › spikelab › calling-c-functions-from-python-104e609f2804
Calling C functions from Python. And how to interact with Numpy arrays… | by Matias Aravena Gamboa | spikelab | Medium
April 21, 2020 - ... The C function takes a pointer to the numpy array, then we use malloc to allocate enough space for our resulting array. Then we iterate over the matrix using a double for loop.
Find elsewhere
🌐
Readthedocs
reptate.readthedocs.io › developers › python_c_interface.html
Tutorial: Interfacing Python and C code — RepTate 1.4.0 documentation
Fortunately, there are many solutions available to write code that will run fast in Python. We can cite Cython or Numba that transform Python code into C executable and require minimal addition to the existing Python code. There is also Ctypes that provides C compatible data types, and allows calling functions from external libraries, e.g.
🌐
YouTube
youtube.com › watch
Calling C Functions from Python - YouTube
#python #cprogramming #pythonprogramming #shorttutorial Hello, this was supposed to be short but ended up becoming longer that's why it's vertical and short,...
Published: January 11, 2024
🌐
Microsoft Learn
learn.microsoft.com › en-us › answers › questions › 5523877 › how-to-call-python-functions-from-c-good-descripti
How to call Python functions from C++, good description - Microsoft Q&A
August 14, 2025 - Write C++ extensions for Python - Visual Studio (Windows) This guide explains how to use the CPython API to expose C++ functions to Python, including how to use PyObject*, PyMethodDef, and PyModuleDef to register and call functions . The Working Programmer - Python: Functions | Microsoft Learn Offers foundational understanding of Python functions, including eval, exec, and dir, which are useful when dynamically interacting with Python from C++. References
🌐
DigitalOcean
digitalocean.com › community › tutorials › calling-c-functions-from-python
Calling C Functions from Python | DigitalOcean
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation. ... Full documentation for every DigitalOcean product. ... The Wave has everything you need to know about building a business, from raising funding to marketing your product.
🌐
Reddit
reddit.com › r/learnpython › python libraries that use c: how do they work? i go the python function definitions in the source code and they’re blank
r/learnpython on Reddit: Python libraries that use C: how do they work? I go the Python function definitions in the source code and they’re blank
November 11, 2023 -

For example, PyTorch works this way. You go to the source code for various functions and they’re blank. I assume there’s some way of linking the definitions to the C code that implements them, but how does this work exactly?

Top answer
1 of 5
33
Those definitions you're seeing are likely type hinting stubs - the actual code is in the C library, and the stubs are only used by your IDE to provide documentation and type signature information.
2 of 5
29
Python can directly call c functions. In python everything is an object but this object knows (or python knows) how to convert it to something that c understands. For example, if I say a = 23, although 23 is an integer, python stores it in an object which is why we are able to do str(23) and we get "23" as string. Same way if I ask python to extract an integer (or string or pointer) out of that object, it can do that (provided data in that object is convertible to that type like it can't extract an integer out of "kjl") So python can produce basic datatypes that typed languages can understand. That's half the work. Now how to communicate with functions? There is already an establish way of doing that like how c linker puts all objects together, links then with lib or so or dll files and gives us a binary. There are calling conventions involved which are kinda standard. They are called ABI (application binary interface). Using this python can call functions that are in some library or so or dll file. Those things are already compiled to machine language so that processor understand them. If I tell python I have a function in some lib file and it is like int add(int, int) and call it from python like x = add(g, h), python understands that it has to convert g and h to integers, call the function in that lib file. Return value is an integer so python creates a python object, fills it with whatever integer it received back from lib function and voila, x contains the answer. There is another way, instead of making python do the work of converting datatypes (from python objects to basic types), I can choose to consume python object in my c code. But for that I (or rather c compiler) needs to know structures of python objects. That information can be obtained using modules like pybind11 etc. Now if I do x = add(g, h), I get python objects and it's my job to extract integers out of g and h and converr my result back to a python object. This ability of python to communicate with other languages, the interoperability is what makes it so popular. I can move complex code to compiled language and keep my main glue code in python only.
🌐
3D Slicer
discourse.slicer.org › development
Calling Python from C++ - Development - 3D Slicer Community
August 1, 2019 - Hi, as the title suggests, the question is whether there is a possibility to call a scripted python module from C++, and if yes, how to do that.
🌐
The Meta Bytes
themetabytes.com › 2018 › 12 › 08 › calling-python-code-from-a-c-application
Calling Python code from a C++ application – The Meta Bytes
December 8, 2019 - If you are using Python3, you would do: PyImport_AppendInittab("art_wrapper", PyInit_art_wrapper); prior to the Py_Initialize call. (the art_wrapper part of the function name is the cython module name, substitute your module name) UPDATE: As Zoltan Beck kindly points out in the comments, this is incomplete.
🌐
Visual Studio Code
code.visualstudio.com › docs › languages › python
Python in Visual Studio Code
November 3, 2021 - This article provides only an overview of the different capabilities of the Python extension for VS Code. For a walkthrough of editing, running, and debugging code, use the button below. ... The tutorial guides you through installing Python and using the extension. You must install a Python interpreter yourself separately from the extension.
🌐
Online Python
online-python.com
Online Python - IDE, Editor, Compiler, Interpreter
Online Python IDE is a web-based tool powered by ACE code editor. This tool can be used to learn, build, run, test your python script. You can open the script from your local and continue to build using this IDE. Code and output can be downloaded to local. Code can be saved online using the "share" option which enables to access the code anytime, anywhere using internet.
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › using the raspberry pi › advanced users
Calling C from Python - Raspberry Pi Forums
May 2, 2018 - Hi Rob. Although it was a bit of a faff at first, I found building C extensions to be the best route. The two references I used most were: https://docs.python.org/2/extending/extending.html (there is a similar page for Python3) http://dfm.io/posts/python-c-extensions/ Have fun BBUK
🌐
Mrcet
mrcet.com › downloads › digital_notes › CSE › III Year › PYTHON PROGRAMMING NOTES.pdf pdf
PYTHON PROGRAMMING NOTES.pdf
malla reddy college, best college in engineering, engineering colleges in hyderabad,good colleges in engineering, top engineering college, best college in hyderabad, most placement engineering college, top 10 engineering colleges in hyderabad, top 10 engineering college, best placement engineering ...
🌐
Quora
quora.com › How-do-I-write-a-Python-script-to-run-a-C-program
How to write a Python script to run a C program - Quora
Answer (1 of 6): I assume you want to both compile and run the code! You can follow following steps: Since i am using windows to run the "gcc" command i did these settings: 1. Install DEV-CPP 2. Now set the path of "gcc" file in your environmental variables i.e. "C:\Program Files (x86)\Dev-Cpp\M...
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › using the raspberry pi › beginners
Calling C programs from python script - Raspberry Pi Forums
October 22, 2014 - Did you checked that using C solves the speed problem? As for calling C using subprocess.call(["./c_program"]) will look for the executable binary in the same folder as the current one. Other option is to create Python bindings to C functions and import/execute them in Python.
🌐
Python
python.org
Welcome to Python.org
Python knows the usual control flow statements that other languages speak — if, for, while and range — with some of its own twists, of course.