Хорошо, это похоже на взлом, но, похоже, работает.
#include <boost/python.hpp>
class Meta
{
public:
static boost::python::object
newClass(boost::python::object cls, std::string name, boost::python::tuple bases, boost::python::dict attrs)
{
attrs["foo"] = "bar";
boost::python::object types = boost::python::import("types");
boost::python::object type = types.attr("TypeType");
return type.attr("__new__")(type, name, bases, attrs);
}
};
BOOST_PYTHON_MODULE(meta)
{
boost::python::class_<Meta>("Meta")
.def("__new__", &Meta::newClass)
.staticmethod("__new__");
}
тогда в питоне
from meta import Meta
class Test(object):
__metaclass__ = Meta
print Test, Test.foo
<class '__main__.Test'> bar
Я пробовал некоторые другие вещи, которые не использовали систему boost :: python :: object, но не могли получить ничего, что работало бы так со стороны python.
Хотя, строго говоря, это не метакласс, поскольку он не наследуется от типа, но он ведет себя как единица, потому что тип используется непосредственно в функции newClass при вызове new. Если это не проблема, то, возможно, было бы разумно изменить его с
return type.attr("__new__")(type, name, bases, attrs);
до
return type.attr("__new__")(cls.attr("__class__"), name, bases, attrs);
или что-то подобное, так что вместо типа используется Boost :: Python :: class.