如何连接Python和C程序?

时间:2021-02-15 09:24:41

I have a python-based program that reads serial data off an a port connected to an rs232 cable. I want to pass the data I get here to a C-program that will handle the computation-intensive side of things. I have been checking up the net and all I've found are linux-based.

我有一个基于python的程序,从连接到rs232电缆的a端口上读取串行数据。我想把我得到的数据传递给c程序,它将处理计算密集型的方面。我一直在网上查询,发现的都是基于linux的。

7 个解决方案

#1


4  

Use a pipe and popen

The easiest way to deal with this is probably to just use popen(3). The popen function is available in both Python and C and will connect a program of either language with the other using a pipe.

最简单的处理方法可能就是使用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)

Once you have the pipe, you should probably send yaml or json through it, though I've never tried to read either in C. If it's really a simple stream, just parse it yourself. If you like XML, I suppose that's available as well.

一旦您有了管道,您可能应该通过它发送yaml或json,尽管我从未尝试在c中读取它们。如果您喜欢XML,我想这也是可用的。

#2


7  

My suggestion would be the inline function from the instant module, though that only works if you can do everything you need to in a single c function. You just pass it a c function and it compiles a c extension at runtime.

我的建议是使用来自instant模块的内联函数,但是只有当您能够在一个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)

#3


6  

There a number of ways to do this.

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

  1. The rawest, simplest way is to use the Python C API and write a wrapper for your C library which can be called from Python. This ties your module to CPython.

    最简单的方法是使用Python C API并为您的C库编写一个包装器,该包装器可以从Python调用。这将您的模块与CPython绑定。

  2. The second way is to use ctypes which is an FFI for Python that allows you to load and call functions in C libraries directly. In theory, this should work across Python implementations.

    第二种方法是使用ctypes, ctypes是Python的FFI,允许您直接在C库中加载和调用函数。从理论上讲,这应该适用于Python实现。

  3. A third way is to use Pyrex or it's next generation version Cython which allows you to annotate your Python code with type information that the compiler can convert into compiled code. It can be used to write wrappers too. AFAIK, It's tied to CPython.

    第三种方法是使用Pyrex或下一代Cython版本,该版本允许您使用编译器可以转换为编译代码的类型信息来注释Python代码。它也可以用来编写包装器。AFAIK,它和CPython绑定。

  4. Yet another way is to use SWIG which is a tool that generates glue code that helps you wrap C libraries for use from Python. It's basically the first approach with a helper tool.

    另一种方法是使用SWIG,它是一种生成胶水代码的工具,可以帮助您打包C库,以便从Python中使用。它基本上是第一个使用辅助工具的方法。

  5. Another way is to use Boost Python API which is an object oriented wrapper over the raw Python C API.

    另一种方法是使用Boost Python API,它是在原始Python C API之上的面向对象包装器。

All of the above let you do your work in the same process.

所有这些都让您在相同的过程中完成您的工作。

If that's not a constraint, like Digital Ross suggested, you can simply spawn a subprocess and hand over arguments (either as command line ones or via it's standard input) and have an external process do the work for you.

如果这不是一个约束,就像Digital Ross建议的那样,您可以生成子进程并提交参数(可以作为命令行之一,也可以通过它的标准输入),并让外部进程为您做这些工作。

#4


2  

How many bits per second are you getting across this RS-232 cable? Have you test results that show that Python won't do the crunchy bits fast enough? If the C program is yet to be written, consider the possibility of writing the computation-intensive side of things in Python, with easy fallback to Cython in the event that Python isn't fast enough.

你在RS-232电缆上每秒能传输多少位?您是否测试过测试结果,表明Python不会足够快地完成这些嘎吱作响的工作?如果C程序还没有编写,那么考虑用Python编写计算密集型的方面的可能性,并在Python不够快的情况下轻松返回到Cython。

#5


1  

Indeed this question does not have much to do with C++. Having said that, you can try SWIG - it's multi-platform and allows functional calls from Python to C/C++.

实际上,这个问题与c++没有多大关系。说到这一点,您可以尝试SWIG——它是一个多平台,允许从Python到C/ c++的功能调用。

#6


0  

I would use a standard form of IPC like a socket.

我将使用IPC的标准形式,比如插座。

A good start would be Beej's Guide.

一个好的开始应该是Beej的指南。

Also, don't tag the question with c++ if you are specifically using c. c and c++ are different languages.

另外,如果您特别使用c++,不要用c++来标记问题。c和c++是不同的语言。

#7


0  

I'd use ctypes: http://python.net/crew/theller/ctypes/tutorial.html
It allows you to call c (and c++) code from python.

我将使用ctypes: http://python.net/crew/theller/ctypes/tutories.html,它允许您从python调用c(和c++)代码。

#1


4  

Use a pipe and popen

The easiest way to deal with this is probably to just use popen(3). The popen function is available in both Python and C and will connect a program of either language with the other using a pipe.

最简单的处理方法可能就是使用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)

Once you have the pipe, you should probably send yaml or json through it, though I've never tried to read either in C. If it's really a simple stream, just parse it yourself. If you like XML, I suppose that's available as well.

一旦您有了管道,您可能应该通过它发送yaml或json,尽管我从未尝试在c中读取它们。如果您喜欢XML,我想这也是可用的。

#2


7  

My suggestion would be the inline function from the instant module, though that only works if you can do everything you need to in a single c function. You just pass it a c function and it compiles a c extension at runtime.

我的建议是使用来自instant模块的内联函数,但是只有当您能够在一个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)

#3


6  

There a number of ways to do this.

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

  1. The rawest, simplest way is to use the Python C API and write a wrapper for your C library which can be called from Python. This ties your module to CPython.

    最简单的方法是使用Python C API并为您的C库编写一个包装器,该包装器可以从Python调用。这将您的模块与CPython绑定。

  2. The second way is to use ctypes which is an FFI for Python that allows you to load and call functions in C libraries directly. In theory, this should work across Python implementations.

    第二种方法是使用ctypes, ctypes是Python的FFI,允许您直接在C库中加载和调用函数。从理论上讲,这应该适用于Python实现。

  3. A third way is to use Pyrex or it's next generation version Cython which allows you to annotate your Python code with type information that the compiler can convert into compiled code. It can be used to write wrappers too. AFAIK, It's tied to CPython.

    第三种方法是使用Pyrex或下一代Cython版本,该版本允许您使用编译器可以转换为编译代码的类型信息来注释Python代码。它也可以用来编写包装器。AFAIK,它和CPython绑定。

  4. Yet another way is to use SWIG which is a tool that generates glue code that helps you wrap C libraries for use from Python. It's basically the first approach with a helper tool.

    另一种方法是使用SWIG,它是一种生成胶水代码的工具,可以帮助您打包C库,以便从Python中使用。它基本上是第一个使用辅助工具的方法。

  5. Another way is to use Boost Python API which is an object oriented wrapper over the raw Python C API.

    另一种方法是使用Boost Python API,它是在原始Python C API之上的面向对象包装器。

All of the above let you do your work in the same process.

所有这些都让您在相同的过程中完成您的工作。

If that's not a constraint, like Digital Ross suggested, you can simply spawn a subprocess and hand over arguments (either as command line ones or via it's standard input) and have an external process do the work for you.

如果这不是一个约束,就像Digital Ross建议的那样,您可以生成子进程并提交参数(可以作为命令行之一,也可以通过它的标准输入),并让外部进程为您做这些工作。

#4


2  

How many bits per second are you getting across this RS-232 cable? Have you test results that show that Python won't do the crunchy bits fast enough? If the C program is yet to be written, consider the possibility of writing the computation-intensive side of things in Python, with easy fallback to Cython in the event that Python isn't fast enough.

你在RS-232电缆上每秒能传输多少位?您是否测试过测试结果,表明Python不会足够快地完成这些嘎吱作响的工作?如果C程序还没有编写,那么考虑用Python编写计算密集型的方面的可能性,并在Python不够快的情况下轻松返回到Cython。

#5


1  

Indeed this question does not have much to do with C++. Having said that, you can try SWIG - it's multi-platform and allows functional calls from Python to C/C++.

实际上,这个问题与c++没有多大关系。说到这一点,您可以尝试SWIG——它是一个多平台,允许从Python到C/ c++的功能调用。

#6


0  

I would use a standard form of IPC like a socket.

我将使用IPC的标准形式,比如插座。

A good start would be Beej's Guide.

一个好的开始应该是Beej的指南。

Also, don't tag the question with c++ if you are specifically using c. c and c++ are different languages.

另外,如果您特别使用c++,不要用c++来标记问题。c和c++是不同的语言。

#7


0  

I'd use ctypes: http://python.net/crew/theller/ctypes/tutorial.html
It allows you to call c (and c++) code from python.

我将使用ctypes: http://python.net/crew/theller/ctypes/tutories.html,它允许您从python调用c(和c++)代码。