从C++运行Python程序的三种方法

一个经常出现的问题是:如何从我的C程序中调用Python?有很多方法,所以让我们回顾其中的三个。
系统方法
我们可以通过使用系统函数来调用C程序中的Python,这基本上意味着我们确实需要编写的Python程序,或者您需要制作C程序编写Python程序来磁盘。这是一个快速示例:

选择 | 换行 | 行号
  1. #include <stdio.h>
  2.  
  3. int main(){
  4.  
  5. char *prg = (char*)"print \"hello from python\"\n";
  6. FILE *f= (FILE*)fopen("test2.py","w");
  7. fprintf(f, prg);
  8. fclose(f);
  9.  
  10. system("python test2.py");
  11.  
  12. }
  13.  

假设该程序被保存为test2.c,那么您将以以下方式进行编译:
GCC Test1.C
然后,您会这样运行:
./a.out
这种方法的坏事是:如果我们要在Python做任何事情,并且我们希望Python输出某些东西,然后我们可以在C中进行处理?我们可以使我们的python程序写入文件,然后我们可以让C程序从Python程序中读取输出的文件,但是您必须对Python程序进行一些修改,并且您将拥有很多文件,结果浮动围绕。在您的硬盘上(就像那里还不够!)
过程方法
让我们制作一个玩具程序,我们想在Python中添加两个数字,这是从C程序中给我们的。因此,C程序将为我们提供两个数字,然后将两个数字发送到Python程序,结果将通过printf命令从C程序编写。

选择 | 换行 | 行号
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(){
  5. int number1 = 10;
  6. int number2 = 32;
  7. int number3 = -1;
  8.  
  9. /* the python program as a C string */
  10. char *prg = (char*)"import sys\nprint int(sys.argv[1])+int(sys.argv[2])\n";
  11. /* make a C string which call Python */
  12. char *input = (char*)malloc(sizeof(100)*sizeof(char));
  13. /* a C string which will store the results */
  14. char *input2 = (char*)malloc(sizeof(100)*sizeof(char));
  15. FILE *f= (FILE*)fopen("test2.py","w");
  16. fprintf(f, prg);
  17. fclose(f);
  18. sprintf(input,"python test2.py %d %d",number1,number2);
  19. f = popen(input,"r");
  20. fgets(input2,100,f);
  21. fclose(f);
  22. number3 = atoi(input2);
  23. printf("%d\n",number3+10);
  24.  

在这里,我们使用Popen打开一个过程,在这种情况下,该过程恰好是运行我们将其定义为C字符串的程序的Python解释器。我们可以阅读该过程的结果,在我们的情况下,该过程将为42。然后,我们将此字符串转换为带有ATOI的INT。
假设该程序被保存为test2.c,那么您将以以下方式进行编译:
GCC test2.c
然后,您会这样运行:
./a.out
嵌入式方法
如果您设备没有操作系统怎么办?或者,也许您不希望您的程序干扰操作系统?一种可能性是将Python嵌入您的C程序中。现在,"嵌入"实际上是什么意思?好吧,这意味着,使口译员的一部分是您的C计划
首先,您正在使用哪种系统? (您可能会停在Windows的最后一部分中的某个地方,因为我认为Popen在Windows API中被称为Popen)。
假设您正在使用Ubuntu或类似的东西。首先,我们需要弄清楚将Python编译和嵌入您的C程序中的标志。包含文件在哪里,库文件在哪里?
我首先弄清楚我在系统上运行的python
python- version
返回:
Python 2.6.5
现在我想弄清楚.h文件在哪里,所以我输入:
找到python.h
返回:
/USR/include/python2.6/python.h
然后,我想找到库文件(基本上是Python解释器):
找到libpython2.6.a
/USR/lib/python2.6/config/libpython2.6.a
然后我得到了我需要的所有东西,现在,让我们确保在做任何事情之前就得到这项工作 别的。
我们首先制作一个空的C程序

选择 | 换行 | 行号
  1. #include <Python.h>
  2. #include <stdio.h>
  3.  
  4. int main(){
  5.  
  6. }

我们会汇编吗?让我们将其保存为test3.c
gcc -i/usr/include/python2.6/-l/usr/lib/python2.6/config/-lpython2.6 test3.c
它起作用了吗?如果是,那么让我们继续在test3.c中使用Python程序进行有趣的C。该计划应该做早些时候做的事情;我们有两个数字(编号1和编号2),我们希望python添加这两个数字,然后我们要在Python中获得添加的结果,并将其放在C中的变量中

选择 | 换行 | 行号
  1. #include <stdio.h>
  2. #include <Python.h>
  3.  
  4. int main(){
  5. int number1 = 10;
  6. int number2 = 32;
  7. Py_Initialize();
  8. char *input = (char*)malloc(sizeof(100)*sizeof(char));
  9. sprintf(input,"number3 = %d + %d",number1,number2);
  10. PyRun_SimpleString(input);
  11. PyObject * module = PyImport_AddModule("__main__");
  12. PyObject * dictionary = PyModule_GetDict(module);
  13. PyObject * result = PyDict_GetItemString(dictionary, "number3");
  14. long number3 = PyInt_AS_LONG(result);
  15. printf("%d\n",(int)number3);
  16. Py_Finalize();
  17. }
  18.  

您通常将其运行为:
./a.out
在这种情况下,我们不需要将Python称为一个单独的过程,因为Python已经是您C程序的一部分。现在您应该使用哪一个?编译C程序时,您必须小心的嵌入式版本的缺点。优点是您不会干扰计算机上的流程,而是将文件写入硬盘驱动器等。

# 回答1

在我看来,您将使用每种解决方案来解决特定类别的问题。
顺便说一句,我不喜欢"系统"方法,因为您将创建与BASH(或SH)命令行输入完全兼容的字符串。
fork()和exec()方法可能更好。如果没有其他原因,则不需要编码参数。
"过程方法"具有与"系统"方法相同的问题。
作为嵌入式解释器运行Python是可以的,但是重点是什么?

如果您要做的就是运行python,为什么还要打扰C呢?


当您动态创建非平凡的Python时,这可能很有价值,但是很少有应用程序会这样做。


如果您要做的只是创建python以匹配一些参数,则这并不有价值。可以在固定程序中对包含/排除的代码块进行警惕。

最重要的是,执行子过程仅在以下情况下才有意义。

目标语言使您可以轻松解决问题,否则这在C中很困难。


您无法访问子过程的来源。


您不想重新实现C中现有的调试程序。(这是非常合理的)。


并行执行是有价值的 - 子过程在C进程做其他事情时会做一些事情。

您将选择的模型在很大程度上取决于您的目标。您是否只需要根据调用参数从Python发出的输出,还是要在两者之间来回传输数据?
您的问题确实很好,尽管没有明确的答案。
干杯!

标签: python

评论已关闭