2012-01-16 6 views
5

Mam następujący kod w C++:Przestrzenie nazw mieszać się po powrocie scoped enum z metody klasy

class Person 
{ 
    public: 
     enum Gender {Male, Female}; 

     Gender GetGender() const; 
} 

owinąłem go w boost :: python w ten sposób:

BOOST_PYTHON_MODULE(TestPython) 
{ 
    scope the_scope = class_<Person>("Person") 
     .def("GetGender", &Person::GetGender); 

    enum_<Person::Gender>("Gender") 
     .value(Male, Person::Male) 
     .value(Female, Person::Female) 
     .export_values(); 
} 

gdy próbuję zadzwonić person.GetGender() z Pythonem otrzymuję następujący wyjątek:

 
Can't pickle : attribute lookup **PyBF.TestPython.Gender**. 
It guesses the namespace of the Gender (which is actually **PyBF.TestPython.Person.Gender**) enum return type incorrectly. 

Jak mogę powiedzieć GetGender FUNCT jon, jaki typ zwrócić bezpośrednio?

+2

Istnieje pewna dziwność w ugotowaniu wyłudzeń. zobacz tutaj: http://stackoverflow.com/questions/3214969/ –

Odpowiedz

1

Ponieważ nie mamy kod, który generuje błąd, ja zakładam, że występuje podczas próby pickle obiektu Person.

Twój problem nie jest związany z użyciem boostu. Leży w module cPickle. Ma problem z wytrawianiem obiektów z klasami zagnieżdżonymi. Zobacz to answer, aby uzyskać wyjaśnienie. Oto prosty przykład kodu, który generuje błąd:

import cPickle 

class MyOuterClass(object): 
    class MyInnerClass(object): 
     pass 

    def __init__(self): 
     self.my_inner_class = self.MyInnerClass() 


def pickle_error(): 
    print "Pickling ..." 
    my_outer_class = MyOuterClass() 
    print cPickle.dumps(my_outer_class) 

if __name__ == "__main__": 
    pickle_error() 

Running produkuje ten wyjściowe:

Pickling ... 
Traceback (most recent call last): 
    File "pickle.py", line 18, in <module> 
    pickle_error() 
    File "pickle.py", line 15, in pickle_error 
    print cPickle.dumps(my_outer_class) 
cPickle.PicklingError: Can't pickle <class '__main__.MyInnerClass'>: 
attribute lookup __main__.MyInnerClass failed 

Jak wspomniano w połączonej odpowiedzi, kiedy cPickle pyta wewnętrzną klasę dla swojej nazwy powraca '__main__.MyInnerClass'. Jednak tej nazwy nie można znaleźć w przestrzeni nazw modułu, stąd masz wyjątek.

Teraz możesz tego doświadczyć, ponieważ ponieważ nie ma czegoś podobnego do typu wyliczeniowego w pytonie, zwiększ go, aby go reprezentować. Konstrukt enum_ deklaruje klasę w bieżącym zakresie. Przechwytując zakres klasy, kończysz tworzenie klasy zagnieżdżonej w osobie i otrzymujesz błąd pikle opisany powyżej.

Istnieje kilka rozwiązań twojego problemu.

Najprostszym byłoby zadeklarowanie enum poza zakresem podmiotu. Możesz nie chcieć ujawnić wyliczenia pokrewnego osoby oprócz tego dla organizacji kodu. Następnie możesz zadeklarować klasę Person w podmodule, dzięki czemu Twoje wyliczenie zostanie ogłoszone w pobliżu twojej klasy, nie będąc zbyt publicznym.

Można również rzucić okiem na boost's pickle support. Jednak nie próbowałem tego.

Trzecim rozwiązaniem może być użycie czegoś innego niż pikle do przechowywania obiektu.

1

Czy to możliwe, że gdzieś masz innego mężczyznę, kobietę? w przeciwnym razie nie rozumiem, jak to się kompiluje. Spróbuj dodać zakresu klasy:

enum_<Person::Gender>("Gender") 
    .EXPORT_ENUM_VALUE(Person::Male) 
    .EXPORT_ENUM_VALUE(Person::Female) 
    .export_values(); 
+0

Przepraszam, że zaktualizowałem wpis, nie skopiowałem całkowicie kodu, mam nadzieję, że teraz ma sens – Grim