在C/C++中嵌入Python

5
作为计算机科学专业的毕业项目,我正在制作一款益智视频游戏,帮助人们学习Python编程。设计中最重要的部分是创建有吸引力的难题,用户可以逐步解决。然而,我目前所面临的问题并不在于难题设计。
最初的想法是让每个“问题”都有一个预期答案数组,检查用户的答案是否正确。但是我们学校计算机科学系主任(负责毕业研讨会)建议我使用Python嵌入式编程。他推荐这样做既是为了挑战我,同时也为了更方便地嵌入一个简单的解释器来检查用户代码输出与预期输出是否一致。
经过四周的学习,我对Python的工作原理有了很大的了解。我甚至使解释器能够接受“简单C字符串”作为Python代码,例如print("hello")或print("hello/tworld"),只要C字符串中没有空格即可。
以下是该代码:
#include "pch.h"
#include <iostream>
#include <string>
#include <fstream>
#include <Python.h>

void exec_pycode(const char* code);

int main()
{
    using namespace std;
    Py_Initialize();

    string input;

    cin >> input;
     /*Though the variable gets passed to a const char* definition,
    the pointer is constant over the character, because the pointer ALWAYS points
    to the same function*/
    char const *PyCode = input.data();

    exec_pycode(PyCode);        

    Py_Finalize();
    return EXIT_SUCCESS;    
}        

//The execution of python code as a simple string in C and interpreting in python
void exec_pycode(const char* code)
{
    Py_Initialize();
    PyRun_SimpleString(code);
    Py_Finalize();
}

我决定的下一步是让像print(“hello world”)这样带有空格的字符串变得可读,就像Python代码一样。

我尝试修改exec code函数的格式如下:

void exec_pycode(const char* code)
{
    Py_Initialize();
    const char *inFile = "FileName";
    PyObject *dict = PyDict_New();
    Py_CompileString(code, inFile, Py_file_input);
    PyRun_String(code, Py_file_input, dict, dict);

    Py_Finalize();
}

当我更改函数后,它可以编译通过。但是,无论我输入的字符串是简单还是包含空格,在输出任何Python代码之前,程序都会以返回值0退出。

我很好奇为什么会出现这种情况,是因为我将用户输入转换为足够的C字符串以便读取为Python代码时出现问题,还是不理解Py_CompileString(const char *str,const char *filename,int start)PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)的声明? 我看过这份文档,做了笔记和图表,但仍然遇到相同的退出条件

我还想知道:

  1. 我是否在为Python字符串命令声明字典以正确读取代码,还是
  2. 我的Python文件标志设置为在简化版本中为NULL而非Py_CompileStrngFlags(...)Py_RunStringFlags(...)是否导致我遇到的返回值为空的问题。
  3. 我是否使用了正确的函数来运行嵌入式Python和用户输入。

1
你忽略了每个函数的返回值。这意味着你无法检测错误,也意味着你根本无法使用编译后的代码(并泄漏其内存)。我怀疑完全空的字典同时阻止了 print 的工作。 - Davis Herring
1
@DavisHerring - 关于完全空的字典:是的,它将缺少打印 - DavidW
1
Py_CompileString 返回编译后的代码对象作为其返回值... - Antti Haapala -- Слава Україні
1个回答

3

您的程序中没有必要使用C标签。您的问题只与C++代码有关。首先,

string input;

cin >> input;

读取一个由空格分隔的单词,类似于C语言中的scanf("%s", input);。你需要使用

getline(cin, input);

下一个问题是,input.data()可能不是以零结尾的。您必须使用input.c_str()

最后:您必须始终检查调用的每个Python API函数的返回值。没有允许的捷径。

4
自 C++11 起,data() 已经变成了以空字符结尾的字符串。 - Davis Herring

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接