将许多数据从Python传递到C程序

时间:2011-02-10 18:45:36

标签: python c dll parameter-passing

我有一个Python脚本和一个C程序,我需要从Python脚本中传递大量数据,这些数据调用C程序很多次。现在我让用户选择用ASCII文件或二进制文件传递它们,但两者都很慢而且没用(我的意思是如果你想存储数据文件很有用,但是我删除了这些文件。脚本)。

os.system不起作用,参数太多,因为C程序也使用文件将数据返回给Python,但这个数据要少得多。

我想知道我可以用什么来快速进行这种交换。将文件写入RAM磁盘?如果是这样,我该怎么做?

我听说可以使用ctypes从DLL调用函数,但不知道如何将我的程序编译为DLL(我在Windows 7 64上使用wxdevc +)。 或者包装它,但仍然不知道它是否可以工作,是否有效。

数据是3D网格的顶点。

我在另一个程序(blender(开源)中运行Python脚本,并且多次调用(通常超过500次)因为它在一个循环内。脚本发送顶点信息(1 { {1}}索引和3个浮点坐标)到程序,程序应该返回许多顶点(只有int索引,因为我可以用Python找到相应的顶点)。

所以这不是交互式的,它更像是一个函数(但它是用C编写的)。我正在编写的脚本+ C程序(它是blender的附加组件)应该是跨平台的,因为它将被重新分发。

该程序实际上是用C语言编写的,从Python中我可以知道包含顶点数据的结构在内存中的地址。如果只知道如何做到这一点,最好只传递给C程序一个地址,并从那里找到所有其他顶点(存储在列表中)。

但据我所知,我无法访问另一个程序的内存空间,我不知道是否使用管道或任何初始化新线程调用程序或在脚本内运行(即实际上是在Blender线程下运行的)

Here is the sourceint应该是结构定义

4 个答案:

答案 0 :(得分:7)

管道是显而易见的方式;如果你的c程序接受来自stdin的输入,你可以使用Popen。这不会像您在编辑中所说的那样创建“线程”;它创建了一个带有单独内存的全新进程

from subprocess import Popen, PIPE

input = "some input"
cproc = Popen("c_prog", stdin=PIPE, stdout=PIPE)
out, err = cproc.communicate(input)

这是一个更详细的例子。首先,一个简单的c程序回应stdin:

#include<stdio.h>
#include<stdlib.h>
#define BUFMAX 100

int main() {
    char buffer[BUFMAX + 1];
    char *bp = buffer;
    int c;
    FILE *in;
    while (EOF != (c = fgetc(stdin)) && (bp - buffer) < BUFMAX) {
        *bp++ = c;
    }
    *bp = 0;    // Null-terminate the string
    printf("%s", buffer);
}

然后是一个python程序管道输入(在这种情况下从argv)到上面的:

from subprocess import Popen, PIPE
from sys import argv

input = ' '.join(argv[1:])
if not input: input = "no arguments given"
cproc = Popen("./c_prog", stdin=PIPE, stdout=PIPE)
out, err = cproc.communicate(input)
print "output:", out
print "errors:", err

但是,如果你不打算在没有python前端的情况下使用c程序,你可能最好使用instant内联c函数。

from instant import inline
c_code = """
    [ ... some c code ... ] //see the below page for a more complete example.
"""
c_func = inline(c_code)

正如Joe指出的那样,你也可以在c:Extending Python with C or C++

中编写一个python模块

这个答案讨论了组合c和python的其他方法:How do I connect a Python and a C program?

编辑:基于你的编辑,听起来你真的应该创建一个cpython扩展。如果你想要一些示例代码,请告诉我;但是一个完整的解释会导致一个不合理的长期答案。请参阅上面的链接(扩展Python ...),了解您需要了解的所有内容。

答案 1 :(得分:4)

如果您的操作系统支持,named pipes是文件的替代品。

答案 2 :(得分:1)

这是一个与其他人略有不同的想法:将您的C程序编写为Python模块。 Here是您完成此操作所需的所有信息。然后,您可以在Python代码和C代码之间来回传递大缓冲区。

答案 3 :(得分:0)

我从未对连接python和C的答案感到满意所以我经过大量的研究和思考后写了一个答案。

TEST.C

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp;
    char path[1035];

    fp = popen("python3 output2.py", "r");  // Open the command for reading.
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit(1);
    }

    while (fgets(path, sizeof(path), fp) != NULL)
       printf("C received %s", path);  // Read the output. 

    pclose(fp);  // close 

   return 0;
}

output2.py

import time
import os, sys

i = 0
while True :
    print("%d" %(i), flush=True)
    time.sleep(1)
    i = i + 1