使用Boost::Python获取一个指向Python实例的c++指针

Get a c++ pointer to a Python instance using Boost::Python

本文关键字:Python 实例 c++ 指针 一个 获取 Boost 使用      更新时间:2023-10-16

我正在将Python嵌入C++应用程序中。当我在Python中创建一个新对象时,我希望能够在C++应用程序中存储对该对象的引用,以便以后可以调用该对象上的方法。推荐的方法是什么?

例如,我希望能够做这样的事情:

实体.py

class Entity:
    def getPointer(self)
        return pointertoSelf;

Manager.cpp

Py_Initialize();
PyRun_SimpleString("import Entity");
PyRun_SimpleString("entity = Entity.Entity()");
pointerToPythonObj* = somehowGetPointerToObj("entity");

建议的方法是查询创建entity对象的命名空间,然后将entity对象的句柄存储为boost::python::object。当与C++中的Python对象交互时,最好尽可能使用boost::python::object,因为它提供了一种高级表示法,其作用非常类似于Python变量。此外,它还提供了适当的引用计数来管理Python对象的生存期。例如,存储一个原始指针(即pointerToPythonObj*)不会延长Python对象的寿命;如果Python对象是从解释器内垃圾收集的,那么pointerToPythonObj将是一个悬空指针。


以下是一个示例:

实体.py:

class Entity:
    def action(self):
        print "in Entity::action"

main.cpp:

#include <boost/python.hpp>
int main()
{
  namespace python = boost::python;
  try
  {
    Py_Initialize(); // Start interpreter.
    // Create the __main__ module.
    python::object main = python::import("__main__");
    python::object main_namespace = main.attr("__dict__");
    // Import Entity.py, and instantiate an Entity object in the
    // global namespace.  PyRun_SimpleString could also be used,
    // as it will default to running within and creating 
    // __main__'s namespace.
    exec(
        "import Entityn"
        "entity = Entity.Entity()n"
      , main_namespace
    );
    // Obtain a handle to the entity object created from the previous
    // exec.
    python::object entity = main_namespace["entity"];
    // Invoke the action method on the entity.
    entity.attr("action")();
  }
  catch (const python::error_already_set&)
  {
    PyErr_Print();
  }
}

运行上述程序会产生以下输出:

实体::操作中的

如果Entity.py无法导入,则可能需要将其包含目录添加到PYTHONPATH环境变量中。