2012-01-29 17 views
14

Interfejs API języka Python C ma obiekt PyObject *PyType_Type, który jest równoważny z type w tłumaczu. Jeśli chcę zdefiniować metaclass w C++, jak ustawić type jako jedną z jego baz w Boost.Python? Co jeszcze powinienem wziąć pod uwagę przy definiowaniu metaklasu Pythona w C++?Jak zdefiniować metakl Pythona za pomocą Boost.Python?

Byłoby idealnie, gdyby istniało rozwiązanie Boost.Python do tego. Jeśli nie, rozwiązanie wykorzystujące API Python C (lub kombinację Boost i C API) również jest dobre. Ponieważ moje inne klasy są wystawione na działanie Boost, wolałbym zostawić SWIG w ostateczności.

Uwaga: To jest rzeczywiście częścią większego problemu Próbuję rozwiązać, którego poprosiłem o w Setting metaclass of wrapped class with Boost.Python, jeśli jesteś zainteresowany.

+0

Szukacie tylko rozwiązań Boost.Python? Myślę, że mogę to rozwiązać z SWIG :) – Flexo

+0

@awoodland Boost.Python jest lepszy, ale nie jestem przeciwny SWIG. –

+0

OK, jeśli nie otrzymasz dobrej odpowiedzi Boost.Python, zadzwoń do mnie, aby przypomnieć mi o innym @, a przyjrzę się temu przy pomocy SWIG. – Flexo

Odpowiedz

4

Okej, to wygląda jak włamanie, ale wygląda na to, że działa.

#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__"); 
} 

następnie w Pythonie

from meta import Meta 

class Test(object): 
    __metaclass__ = Meta 

print Test, Test.foo 
<class '__main__.Test'> bar 

Próbowałem kilka innych rzeczy, które nie korzystają z systemu pyton boost :: :: obiektu, ale nie mógł się niczego, co pracował tak od strony Pythona .

Chociaż ściśle rzecz biorąc nie jest to metaclass, ponieważ nie dziedziczy po typie, ale zachowuje się jak jeden, ponieważ typ jest używany bezpośrednio w funkcji newClass podczas wywoływania nowego. Jeśli to nie problem to może być mądry, aby zmienić go z

return type.attr("__new__")(type, name, bases, attrs); 

do

return type.attr("__new__")(cls.attr("__class__"), name, bases, attrs); 

lub coś podobnego tak boost :: Python :: klasa jest używana zamiast typu.

+0

Wypróbuję to. Najprawdopodobniej nie będzie działać z Pythonem 3 (jest to wersja, której chciałbym użyć), ale myślę, że jeśli to konieczne, będę ją obniżać. –

+0

jeśli już nie zrobiłeś, to może warto zapytać na http://boost.2283326.n4.nabble.com/Python-c-sig-f2696818.html – babak

+0

Przyznałem ci nagrodę, ponieważ ta odpowiedź jest całkiem dobra, ale ja jeszcze go nie zaakceptuję. Wciąż szukam rozwiązania, które będzie działać również w Pythonie 3. Jeśli nie znajdę żadnej, przyjmuję tę odpowiedź. –

Powiązane problemy