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 № 1Dado 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, is
y issubclass
, ver esta responder.