views:

85

answers:

5

So I have a C program to interface with an i2c device. I need to interface to that device from python. I'm just wondering if it's worth porting the program into a python module or if the amount of effort involved in porting won't outweigh just executing the program using subprocess. I know I'm sure it's different for every application, but I'd like to know if it's even worth my time to learn the python C extensions and port this program.

Update: I have full access to the source of both the C as well as the python. But there is already substantial work done on the python side and I'd like to keep changes to that as minimal is possible, if that matters. And I'd also like to minimize the changes that have to be made to the C. It's doable, but I didn't write it and it involves a lot of by addressing that I'd rather not have to redo.

+2  A: 

There are many ways you can proceed -- the Python C API, which seems to be the one you're considering, but also SWIG, Cython, ctypes... as long as your existing C code can be made into a library (with functions callable "from the outside"), you have a wealth of options. Personally, I'd recommend Cython -- it's looking more and more as a broad subset of Python, extended just enough to allow effective compilation into machine code and direct calling of functions from C libraries.

Alex Martelli
+1 for Cython, but I would argue Cython is a superset of Python.
carl
Do you have a link to an example of implementing Cython using a pre-existing C code? What I've found seems to be writing C code to fit into python
Falmarri
@carl, since Cython doesn't have _all_ the features of Python, how could it be a superset? "extended subset" (which actually describes the relation between _any_ two languages, if taken literally;-) is at least mathematically correct;-).
Alex Martelli
@Falmarri, for one example see http://groups.google.com/group/cython-users/browse_thread/thread/7185d356c4c78c98?pli=1 , for a more systematic treatment http://ldots.org/pyrex-guide/ (uses pyrex, cython's predecessor, but -- apart from when it mention limitations nof pyrex that have gone away in cython;-) -- should still apply). If you need to wrap C++, see http://wiki.cython.org/WrappingCPlusPlus .
Alex Martelli
@Alex Martelli, sure, but I was under the impression that Cython 0.13 was getting pretty close with generators. But, you would know better than I! :-)
carl
@carl, "close but no cigar" is a good assessment -- Cython doesn't really aim to be a complete implementation of Python (though surely _far_ more so than Pyrex ever did!-), the way Jython, IronPython, PyPy, Pynie, etc, aim to be (and in three of the four cases I mentioned, actually _are_ -- though not necessarily of the greatest and latest Python version, to be sure;-). I may well be wrong, but I'd bet a beer that Cython won't be passing the Python test suite any time in the next, oh, say, two years... any takers?-)
Alex Martelli
A: 

Don't use the Python C API, there are much easier alternatives, most notably cython.

cython is a Python-like language, which compiles into C code for the Python c library. Basically it's C with Python syntax and features (e.g. nice for loops, exceptions, etc.). cython is clearly the most recommendable way to write C extensions for python.

You might also want to take a look at ctypes, a module to dynamically load C libraries and call functions from them. If your i2c-code is available as shared library, you can get away with no native binding at all, which eases development and distribution.

lunaryorn
A: 

I've had good luck using ctypes. Whatever you choose, though, you may not gain any time this time but the next time around your effort will be much faster than doing the whole thing in C.

bstpierre
A: 

I would recommend ctypes using a shared library. It would be a good idea however to don't rely on complex types like structs in your C API. Using a pseudo-OOP approach is the simplest to map over to Python.

E.g.

foo_t* foo_new(void);
int foo_bar(foo_t*, int);
int foo_baz(foo_t*, int);
void foo_free(foo_t*);

Here, you could use ctypes native stuff. E.g. c_void_p for your object handle and c_int. c style strings are also supported with create_string_buffer (or something like that).

Maister
A: 

One of the first Python programs I wrote was a script that called functions from a C library, which sounds close to what you're doing. I used ctypes, and I was impressed as to how easy it was: I could access each library function from python by writing just a few lines of python (no C at all!). I'd tried the Python C API before, and it required a lot more boilerplate. I havent tried SWIG or Cython.

Gilles