/ / Boost.Python crea un manejador de tipo - python, c ++, boost-python

Boost.Python create handle from type - python, c ++, boost-python

En algunos lugares al exponer el código C ++ a python, necesito usar un PyObject*. Si tengo una instancia de un boost::python::class_ objeto, puedo invocar ptr() en eso. Pero ¿y si solo tengo el tipo?

Básicamente, dada la lista de tipos boost::python::bases<A, B, C>, Quiero convertir esto en un boost::python::tuple de instancias que puedo pasar en algo como PyErr_NewExceptionWithDoc(). es posible?

Respuestas

1 para la respuesta № 1

Dado un tipo de C ++ T, uno puede crear un boost::python::type_id objeto, y luego consultar en el registro Boost.Python para obtener información de registro. Si se encuentra una entrada en el registro, entonces se puede usar para obtener un identificador de la clase Python creada para el tipo T:

/// @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);
}

Aquí hay un ejemplo completo. demostrando ubicar un objeto de clase Python en el registro Boost.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;
}
}

Salida:

<class "Spam">

Para obtener más funciones relacionadas con el tipo, como aceptar objetos de tipo, isy issubclass, ver esta responder.