使用 C 模块扩展 python
所以我有一个 C 程序来与 i2c 设备交互。我需要从 python 连接到该设备。我只是想知道是否值得将程序移植到 python 模块中,或者移植所涉及的工作量是否不会超过使用子进程执行程序。我知道我确信每个应用程序都是不同的,但我想知道是否值得我花时间学习 python C 扩展并移植这个程序。
更新:我可以完全访问 C 和 python 的源代码。但是 python 方面已经完成了大量的工作,如果这很重要的话,我希望尽可能地对其进行尽可能少的更改。我还想尽量减少必须对 C 进行的更改。这是可行的,但我没有编写它,并且它涉及很多我不想重做的地址。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以通过多种方式继续操作 - Python C API,这似乎是您正在考虑的一种,但也可以 SWIG,Cython,ctypes...只要您现有的 C 代码可以制作成库(具有可“从外部”调用的函数) ),您有丰富的选择。就我个人而言,我推荐 Cython——它越来越像 Python 的一个广泛子集,其扩展足以允许有效编译成机器代码并直接调用 C 库中的函数。
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.我编写的第一个 Python 程序是一个从 C 库调用函数的脚本,这听起来与您正在做的很接近。我使用了 ctypes,它的简单性给我留下了深刻的印象:我只需编写几行 python 即可从 python 访问每个库函数(根本不需要 C!)。我之前尝试过 Python C API,它需要更多的样板文件。我还没有尝试过 SWIG 或 Cython。
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.
不要使用 Python C API,有更简单的替代方案,尤其是 cython。
cython 是一种类似 Python 的语言,可编译为 Python c 库的 C 代码。基本上它是带有 Python 语法和功能的 C 语言(例如很好的 for 循环、异常等)。 cython 显然是为 python 编写 C 扩展的最值得推荐的方法。
您可能还想看看 ctypes,这是一个用于动态加载 C 库并从中调用函数的模块。如果您的 i2c 代码可作为共享库使用,则您可以完全不需要本机绑定,从而简化了开发和分发。
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.
我使用 ctypes 很幸运。不过,无论您选择什么,这次您可能不会获得任何时间,但下次您的努力将比在 C 中完成整个事情快得多。
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.
我建议使用共享库的 ctypes。不过,最好不要依赖 C API 中的结构等复杂类型。使用伪 OOP 方法是映射到 Python 最简单的方法。
例如
,在这里,您可以使用 ctypes 原生的东西。例如,c_void_p 表示对象句柄,c_int 表示。 create_string_buffer(或类似的东西)也支持c风格的字符串。
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.
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).