python - 设置嵌入式 Python 以编写 C++ 游戏脚本

标签 python c++ boost-python

我很难做到这一点。我坚持的是试图将用 C++ 编写的模块暴露给嵌入式 python 解释器。

我正在使用 boost::python,但我不确定我应该为此做什么,至少可以说,似乎缺少文档。

我想要的是使用 BOOST_PYTHON_MODULE 公开一些 C++ 代码,然后从同一应用程序 访问它。但是我无法导入它。我得到的,这似乎是最接近的(只是相关部分):

#include <python/interpreter.hpp>

bp::object blag() {
    return bp::str("Thingy");
}

BOOST_PYTHON_MODULE(modthingy) {
    bp::def("blag", &blag);
}


Interpreter::Interpreter() {
    Py_UnbufferedStdioFlag = 1;
    Py_Initialize();
    try {
        init_module_modthingy();
    } catch (bp::error_already_set) {
        PyErr_Print();
    }

    main_module = bp::import("__main__");
    main_namespace = main_module.attr("__dict__");
}

但是打印错误 AttributeError: 'NoneType' object has no attribute '__dict__' 而且我以后无法导入该模块。

这应该如何构建?

编辑: 好的,所以我得到的最接近的是接受的答案中的一种方法:

PyImport_AppendInittab("modthingy", &PyInit_modthingy);
Py_Initialize();

但是,这对我来说似乎不是特别有用,因为我希望能够在 Initialize 函数之后添加/导入模块。我将研究一些事情,即:

  • 看看我是否可以获得在 python 3 中工作的 python 2 的建议方法
  • 看看我是否可以很好地构建我的游戏,要求在 Py_Initialize 之前命名所有模块

我会用我的发现更新这篇文章。

最佳答案

Boost.Python 使用 BOOST_PYTHON_MODULE定义 Python 模块初始值设定项的宏。结果函数不是模块导入器。这种差异类似于创建 modthingy.py 模块并调用 import modthingy

导入模块时,Python会先检查模块是否为内置模块。如果该模块不存在,则 Python 将搜索 module search path。试图根据模块名称查找 python 文件或库。如果找到一个库,则 Python 期望该库提供一个函数来初始化该模块。一旦找到,导入将在模块表中创建一个空模块,然后对其进行初始化。对于静态链接的模块,例如 modthingy,模块搜索路径将无济于事,因为没有可供它查找的库。

对于嵌入,module table and initialization function文档指出,对于静态模块,除非初始化表中有条目,否则不会自动调用模块初始化函数。对于 Python 2 和 Python 3,可以通过调用 PyImport_AppendInittab() 来完成此操作。之前 Py_Initialize() :

BOOST_PYTHON_MODULE(modthingy)
{
  // ...
}

PyImport_AppendInittab("modthingy", &initmodthingy);
Py_Initialize();
// ...
boost::python::object modthingy = boost::python::import("modthingy");

或者,对于 Python 2,一旦解释器被初始化,就可以创建一个空模块,通过 PyImport_AddModule() 添加到模块字典中。 ,然后显式初始化模块。

BOOST_PYTHON_MODULE(modthingy)
{
  // ...
}

Py_Initialize();
PyImport_AddModule("modythingy");
initmodthingy();
boost::python::object modthingy = boost::python::import("modthingy");

此方法在官方 Python 嵌入式演示中进行了演示,embed/demo.c .从 BOOST_PYTHON_MODULE 创建的模块初始化程序不会调用 PyImport_AddModule(),因此必须显式调用它。

另请注意,用于嵌入的 Python 的 C API 改变了 Python 2 和 3 之间模块初始化函数的命名约定,因此对于 BOOST_PYTHON_MODULE(modthingy),可能需要使用 &initmodthingy 用于 Python 2 和 &PyInit_modthingy 用于 Python 3。


这是一个最小的完整示例,演示了导入与嵌入式解释器静态链接的模块:

#include <iostream>
#include <string>

#include <boost/python.hpp>

std::string spam() { return "Spam spam spam"; }

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::def("spam", &spam);
}

int main()
{
  // Add example to built-in.
  PyImport_AppendInittab("example", &initexample);

  // Start the interpreter.
  Py_Initialize();

  namespace python = boost::python;
  try
  {
    // >>> import example
    python::object example = python::import("example");
    // >>> x = example.spam()
    python::object x = example.attr("spam")();
    // >>> print x
    std::cout << "x = " << python::extract<std::string>(x)() << std::endl;
  }
  catch (const python::error_already_set&)
  {
    PyErr_Print();
  }
}

输出:

x = Spam spam spam

关于python - 设置嵌入式 Python 以编写 C++ 游戏脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28229720/

相关文章:

python,scipy- homework -- 如何在网格中保存粒子位置的历史记录

c++ - 将元素数组分解为最少数量的回文

c++ - 递归:将字符串中的 e 换成 a

python - 如何使用 boost.python 提取 unicode 字符串

python-3.x - 如果使用 anaconda,导入 boost/c++ 时 Python 崩溃

python - 使用 Tweepy API Search 搜索列表中的任何元素

python - PyCharm 报告未使用的局部变量,但此变量已在局部命名空间中使用

python - 更改字符串中的单词以将文本文件大写

c++ 使用空指针访问静态成员

c++ - 为 Boost.Python 包含带有 Bjam 的系统库