繁体   English   中英

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

[英]Setting up embedded Python for Scripting a C++ Game

我在实现这个目标上遇到了麻烦。 我所坚持的是尝试将用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__");
}

但这会打印出Error 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将搜索模块搜索路径,以尝试根据模块名称查找python文件或库。 如果找到了库,则Python希望该库提供一个将初始化模块的函数。 找到后,导入将在modules表中创建一个空模块,然后对其进行初始化。 对于静态链接的模块(例如modthingy ,模块搜索路径将无济于事,因为没有库可供查找。

对于嵌入, 模块表和初始化函数文档指出对于静态模块,除非初始化表中有条目,否则不会自动调用模块初始化器函数。 对于Python 2和Python 3,可以通过在PyImport_AppendInittab()之前调用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的用于嵌入用于Python 2和3之间模块初始化函数改变的命名约定,因此对于C API 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM