将 Python 3.3 嵌入到 C++ 程序中,同时只能从输入中一次读取一行

Posted

技术标签:

【中文标题】将 Python 3.3 嵌入到 C++ 程序中,同时只能从输入中一次读取一行【英文标题】:Embedding Python 3.3 in a C++ program while only able to read one line at a time from input 【发布时间】:2013-05-28 22:29:03 【问题描述】:

我目前正在为一个大型程序添加嵌入式 Python 支持(是的,扩展不是一种选择),作为我暑期实习的一部分。理想情况下,我可以将 Python 支持保留在单个 .DLL 中,该 .DLL 目前包含程序的内部脚本语言,并且是集成所述语言和 Python 的最简单的地方。

但是,由于程序的 API,我只能使用一个输入函数。此函数的返回值是当前输入的单行,可以是控制台或文件。输入接口不能(在 .DLL 中)转换为流对象、缓冲区或 FILE 指针。

我当前的测试代码(在程序之外编写,使用 std::string、istream 和 getline 来限制)是

// start python
Py_Initialize();

try

   cout << "Python " << Py_GetVersion() << endl;
   string block;
   bool in_block = false;
   while ( !cin.eof() )
   
      string str;
      cout << (in_block ? "... " : ">>> "); // prompt string
      getline(cin,str);

      if ( in_block ) // if in an indented block
      
         if ( str.front() != ' ' && str.front() != '\t' ) // if ending the indented block
         
            PyRun_SimpleString(block.c_str());  // run Python code contained in block string
            block.clear();                      // clear string for next block
            in_block = false;                   // no longer in block
         
         else // a component of an indented block
         
            block += (str+'\n'); // append input to block string
            continue;            // do not pass block exit code, do not collect two hundred dollars
         
      

      // either not in an indented block, or having just come out of one
      if ( str.back() == ':' ) // if colon, start new indented block
      
         block = (str+'\n');
         in_block = true;
         continue;
      
      else  PyRun_SimpleString(str.c_str());  // otherwise, run block-free code
   

catch ( error_already_set e )  PyErr_Print(); 

// close python
Py_Finalize();

// done
return 0;

我没有遇到这个 hack 的严重问题,但它让我觉得非常不优雅。谁能想到更好的方法来做到这一点?

我已经和我的老板一起清理了 boost.python 库,如果这提供了一些我没有发现的有用技巧的话。

编辑:我可能应该提到程序本身,虽然不是我微薄的测试平台,但必须在 MS Windows 上运行。

【问题讨论】:

在此澄清一下,您是否尝试嵌入交互式解释器外壳? 【参考方案1】:

您编写的内容看起来与普通解释器表面上相似,但除了最琐碎的情况外,它不会遵循相同的缩进/缩进和延续规则。

嵌入交互式解释器外壳的最简单方法是嵌入一个运行纯 Python 编写的交互式解释器的裸解释器,通常通过 code 模块。

为此,您必须将逐行阅读器连接到嵌入的 stdin 文件对象,但对于任何实际用途,您似乎都需要这样做。 (否则,例如,如果用户在 shell 中键入 input() 会发生什么?)

另一种方法是设置 pty 并针对它运行股票交互式解释器(可能作为子进程),从您的线路阅读器提供 pty 的输入管道。

【讨论】:

这个初始代码并不打算涵盖所有用例,当然也不打算成为一个完整的解释器;我需要为整个程序添加行延续支持之类的东西,但我不想这样做,直到我确定上面的 hack 是唯一的方法。不过,针对伪终端运行股票解释器听起来是个好主意。 实际程序需要在 Windows 上运行这一事实也可能是个问题;不确定操作系统如何处理ptys。 @J.T.Davies:Windows 没有 pty。有各种不同的方法来伪造它。几年前当我不得不做类似的事情时,我为 Windows 和其他所有东西编写了几乎完全独立的代码。 IIRC,Windows代码,而不是假装isatty,实际上启动了一个带有隐藏控制台窗口的真正控制台应用程序作为子进程并与控制台窗口对话,或者类似的可怕的东西。但这可能只是因为我必须处理 Win9x,这可能不是现在的问题…… 我有另一个想法:IDLE 有自己强大的、可移植的包装器,用于运行交互式解释器,它认为自己拥有一个控制台,但实际上是在与 IDLE GUI 对话。我不知道从 IDLE 的其余部分中提取它们有多么容易,但它可能值得一看。 (我相信 IPython 也有类似的“远程处理”支持,但它正在被逐步淘汰,取而代之的是尚未完成的新的基于 zeromq 的设计。)

以上是关于将 Python 3.3 嵌入到 C++ 程序中,同时只能从输入中一次读取一行的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将 C++ 小部件嵌入到 PyQt 应用程序中?

在 Python GUI 中嵌入 C++ 程序

试图将 python 嵌入到 Visual Studio 2010 C++ 文件中,并以代码 1 退出

将 Java 嵌入到 C++ 应用程序中?

将 Java 嵌入到 C++ 应用程序中?

在 C++ 应用程序中嵌入 python 环境