如何连接Python和C程序?
我有一个用Python写的程序,它可以从通过RS232电缆连接的端口读取串行数据。我想把这里获取的数据传递给一个C语言程序,这个程序会处理一些计算量大的任务。我在网上查了一下,发现的都是基于Linux系统的方案。
7 个回答
有很多方法可以做到这一点。
最简单直接的方法是使用 Python C API,为你的 C 库写一个包装器,这样就可以从 Python 调用它。这种方法会把你的模块绑定到 CPython。
第二种方法是使用 ctypes,这是一个为 Python 提供的 外部函数接口,可以直接加载和调用 C 库中的函数。理论上,这种方法应该适用于所有 Python 实现。
第三种方法是使用 Pyrex 或它的下一代版本 Cython,这可以让你在 Python 代码中添加类型信息,编译器可以将其转换为编译后的代码。它也可以用来写包装器。根据我所知,它也是绑定到 CPython 的。
还有一种方法是使用 SWIG,这是一个生成胶水代码的工具,帮助你将 C 库包装起来,以便在 Python 中使用。基本上,这种方法就是第一种方法的一个辅助工具。
另一种方法是使用 Boost Python API,这是一个面向对象的包装器,基于原始的 Python C API。
以上所有方法都可以让你在同一个进程中完成工作。
如果这不是一个限制条件,就像 Digital Ross 提到的,你可以简单地启动一个子进程,并传递参数(可以是命令行参数或通过标准输入),让外部进程为你完成工作。
我建议你使用instant
模块里的inline
函数,不过这个方法只有在你能把所有需要的操作都放在一个C语言函数里的时候才有效。你只需要把这个C语言函数传给它,它就会在运行时编译一个C语言扩展。
from instant import inline
sieve_code = """
PyObject* prime_list(int max) {
PyObject *list = PyList_New(0);
int *numbers, *end, *n;
numbers = (int *) calloc(sizeof(int), max);
end = numbers + max;
numbers[2] = 2;
for (int i = 3; i < max; i += 2) { numbers[i] = i; }
for (int i = 3; i < sqrt(max); i++) {
if (numbers[i] != 0) {
for (int j = i + i; j < max; j += i) { numbers[j] = 0; }
}
}
for (n = numbers; n < end; n++) {
if (*n != 0) { PyList_Append(list, PyInt_FromLong(*n)); }
}
free(numbers);
return list;
}
"""
sieve = inline(sieve_code)
使用管道和popen
处理这个问题最简单的方法可能就是使用 popen(3)
。这个 popen
函数在Python和C语言中都可以使用,它的作用是通过管道把一个程序和另一个程序连接起来。
>>> import subprocess
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args)
一旦你有了这个管道,建议你通过它发送yaml或json格式的数据,虽然我自己在C语言中从来没有尝试过读取这两种格式。如果数据流真的很简单,你可以自己解析一下。如果你喜欢XML格式,我想那也是可以的。