【问题标题】:Pass many pieces of data from Python to C program将多条数据从 Python 传递到 C 程序
【发布时间】:2011-06-25 01:54:30
【问题描述】:

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

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

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

我听说可以使用 ctypes 从 DLL 调用函数,但不知道如何将我的程序编译为 DLL(我在 Windows 7 64 上使用 wxdevc+)。 或者包装一下,但还是不知道能不能用,有没有效率。

数据是 3D 网格的顶点。

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

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

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

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

Here is the sourceblender/source/blender/makesdna/DNA_meshdata_types.h 应该是结构体定义

【问题讨论】:

    标签: python c dll parameter-passing


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      管道是显而易见的选择;如果你的 c 程序接受来自标准输入的输入,你可以使用Popen。正如您在编辑中所说,这不会创建“线程”;它创建了一个具有独立内存的全新进程

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

      这里有一个更详细的例子。首先,一个简单的回显标准输入的 c 程序:

      #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 程序,你最好内联一个 c 函数,也许使用instant

      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 中编写一个 python 模块:Extending Python with C or C++

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

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

      【讨论】:

      • 我写了 C 程序,我可以改变我想要的方式。那么使用管道进行通信就像在标准输入中编写代码一样?
      • 如果我理解正确,是的。我会发布一个示例以防万一。
      • 好的,我理解你的代码。不幸的是,我将重新分发代码,所以我更喜欢只使用标准库(我看到即时是一个外部库)。我会尝试使用管道。我还要打扰你一点:你认为制作一个共享库并用 ctypes 调用它也可以吗?顺便说一句,内联的东西真的很有趣!
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        测试.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;
        }
        

        输出2.py

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-20
          相关资源
          最近更新 更多