如何连接Python和C程序?

2 投票
7 回答
12261 浏览
提问于 2025-04-16 10:17

我有一个用Python写的程序,它可以从通过RS232电缆连接的端口读取串行数据。我想把这里获取的数据传递给一个C语言程序,这个程序会处理一些计算量大的任务。我在网上查了一下,发现的都是基于Linux系统的方案。

7 个回答

7

有很多方法可以做到这一点。

  1. 最简单直接的方法是使用 Python C API,为你的 C 库写一个包装器,这样就可以从 Python 调用它。这种方法会把你的模块绑定到 CPython。

  2. 第二种方法是使用 ctypes,这是一个为 Python 提供的 外部函数接口,可以直接加载和调用 C 库中的函数。理论上,这种方法应该适用于所有 Python 实现。

  3. 第三种方法是使用 Pyrex 或它的下一代版本 Cython,这可以让你在 Python 代码中添加类型信息,编译器可以将其转换为编译后的代码。它也可以用来写包装器。根据我所知,它也是绑定到 CPython 的。

  4. 还有一种方法是使用 SWIG,这是一个生成胶水代码的工具,帮助你将 C 库包装起来,以便在 Python 中使用。基本上,这种方法就是第一种方法的一个辅助工具。

  5. 另一种方法是使用 Boost Python API,这是一个面向对象的包装器,基于原始的 Python C API。

以上所有方法都可以让你在同一个进程中完成工作。

如果这不是一个限制条件,就像 Digital Ross 提到的,你可以简单地启动一个子进程,并传递参数(可以是命令行参数或通过标准输入),让外部进程为你完成工作。

9

我建议你使用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)
5

使用管道和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格式,我想那也是可以的。

撰写回答