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:
- Write the C functions you want to use. (You probably did this already)
- 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)
- Write the ctypes wrapper (It's easier than it sounds, I wrote a how-to for that)
- Call a function from that wrapper in Python. (This is just as simple as calling any other python function)
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:
- Write the C functions you want to use. (You probably did this already)
- 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)
- Write the ctypes wrapper (It's easier than it sounds, I wrote a how-to for that)
- Call a function from that wrapper in Python. (This is just as simple as calling any other python function)
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...
Calling C communication functions via Python?
How to call Python functions from C++, good description
Python libraries that use C: how do they work? I go the Python function definitions in the source code and they’re blank
Calling Python from C++
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?
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?