Boost.Python从类型创建句柄

时间:2016-07-06 14:21:14

标签: python c++ boost-python

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

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

1 个答案:

答案 0 :(得分: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);
}

以下是在Boost.Python注册表中查找Python类对象的完整示例demonstrating

#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 answer。