Boost.Python 从类型创建句柄

Posted

技术标签:

【中文标题】Boost.Python 从类型创建句柄【英文标题】:Boost.Python create handle from type 【发布时间】:2016-07-06 14:21:13 【问题描述】:

在将 C++ 代码暴露给 python 的某些地方,我需要使用PyObject*。如果我有一个boost::python::class_ 对象的实例,我可以在其上调用ptr()。但是如果我只有类型呢?

基本上,给定类型列表boost::python::bases<A, B, C>,我想将其转换为boost::python::tuple 的实例,我可以将其传递为PyErr_NewExceptionWithDoc() 之类的东西。这可能吗?

【问题讨论】:

回想起来,即使这是可能的,显然也不可能创建一个继承自 Python 异常类型和 Boost.Python class_ 的 Python 类型。所以我想这更多的是好奇而不是实用。 【参考方案1】:

给定一个 C++ 类型 T,可以创建一个 boost::python::type_id 对象,然后查询 Boost.Python 注册表以获取注册信息。如果在注册表中找到一个条目,则可以使用它来获取为类型 T 创建的 Python 类的句柄:

/// @brief Get the class object for a wrapped type that has been exposed
///        through Boost.Python.
template <typename T>
boost::python::object get_instance_class()

  // Query into the registry for type T.
  namespace python = boost::python;
  python::type_info type = python::type_id<T>();
  const python::converter::registration* registration =
    python::converter::registry::query(type);

  // If the class is not registered, return None.
  if (!registration) return python::object();

  python::handle<PyTypeObject> handle(python::borrowed(
    registration->get_class_object()));
  return python::object(handle);


这是一个完整的示例 demonstrating 在 Boost.Python 注册表中定位 Python 类对象:

#include <boost/python.hpp>
#include <iostream>

/// @brief Get the class object for a wrapped type that has been exposed
///        through Boost.Python.
template <typename T>
boost::python::object get_instance_class()

  // Query into the registry for type T.
  namespace python = boost::python;
  python::type_info type = python::type_id<T>();
  const python::converter::registration* registration =
    python::converter::registry::query(type);

  // If the class is not registered, return None.
  if (!registration) return python::object();

  python::handle<PyTypeObject> handle(python::borrowed(
    registration->get_class_object()));
  return python::object(handle);


struct spam ;

int main()

  Py_Initialize();

  namespace python = boost::python;
  try
  
    // Create the __main__ module.
    python::object main_module = python::import("__main__");
    python::object main_namespace = main_module.attr("__dict__");

    // Create `Spam` class.
    // >>> class Spam: pass
    auto spam_class_object = python::class_<spam>("Spam", python::no_init);
    // >>> print Spam
    main_module.attr("__builtins__").attr("print")(get_instance_class<spam>());
    // >>> assert(spam is spam)
    assert(spam_class_object.ptr() == get_instance_class<spam>().ptr());
  
  catch (python::error_already_set&)
  
    PyErr_Print();
    return 1;
  

输出:

<class 'Spam'>

有关更多类型相关功能,例如接受类型对象isissubclass,请参阅this 答案。

【讨论】:

以上是关于Boost.Python 从类型创建句柄的主要内容,如果未能解决你的问题,请参考以下文章

Boost.Python 从 C++ 创建对现有 Python 对象的新引用

使用 Boost Python 从 c++ 类创建派生的 Python 类

Boost.Python 返回一个不可复制对象的列表

boost::python - 如何从 C++ 在自己的线程中调用 python 函数?

Boost.Python 无法解析传递给函数的派生类型

Boost python /从线程导入模块需要ReleaseLock()。为啥?