Ответ 1
Хорошо, это похоже на хак, но, похоже, это работает.
#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__");
}
а затем в python
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.