Czy mogę wystawić C++ enum
na SWIG jako rzeczywistej jednostki zamiast zestawu stałych, więc mogę wyliczyć nad nimi w kodzie Pythona?Jak wyliczyć członków enum za pomocą SWIG
Odpowiedz
Napotkałem ten sam problem. Mam nadzieję, że SWIG wkrótce obsługuje C++ 11: enum class
.
Oto hack, który przekonuje SWIG umieścić teksty stałe w strukturze:
#ifdef SWIG
%rename(MyEnum) MyEnumNS;
#endif
struct MyEnumNS
{
enum Value { Value1, Value2, Value3 };
};
typedef MyEnumNS::Value MyEnum;
W .cpp
kod, który teraz musi używać MyEnum::Value1
w kodzie Pythona to MyEnum.Value1
. Chociaż zawikłany, typedef
uniemożliwia zmianę istniejącego kodu, który używa enum wszędzie, a zmiana nazwy SWIG% sprawia, że enum mają tę samą nazwę w opakowaniu SWIG.
W Pythonie można wyliczyć wartości z odrobiną kodu:
def values(enum):
return [(k,v) for k,v in vars(enum).items() if isinstance(v,int)]
To nie jest ładna, i chciałbym zobaczyć lepsze rozwiązanie.
jestem całkiem pewny szukasz są ...
typemaps: Ponieważ rodzaj manipulacja jest tak centralny do generowania kodu wrapper, SWIG pozwala mu być całkowicie zdefiniowana (lub nowo) przez użytkownika. Aby to zrobić, używana jest specjalna dyrektywa% typemap. (SWIG Doc2.0)
Aby uzyskać wszystkie informacje, jakich można potrzebować w przypadku map typów, tutaj znajduje się link do dokumentacji SWIG na ten temat. http://www.swig.org/Doc2.0/Typemaps.html#Typemaps_nn2
Typemaps powinno umożliwić informowanie SWIG o konwersji wyrażeń w języku C++ na żądane obiekty Pythona.
@ Flexo, tbh, nie wiedziałem o typemapach, jestem nowy w SWIG, po prostu użyli go w projekcie w niektórych ciemniejszych częściach, działało i nikt się tym nie przejmował, ale potem zdecydowałem się go rozszerzyć kawałek. – unkulunkulu
Możemy stworzyć coś, co pozwoli ci wyliczyć w Pythonie, przy stosunkowo niewielkiej ingerencji w nagłówki C++, które zawija. Na przykład, jeśli mamy plik nagłówka:
#ifndef PYTHON_ENUM
#define PYTHON_ENUM(x) enum x
#endif
PYTHON_ENUM(TestName) {
foo=1,
bar=2
};
PYTHON_ENUM(SomeOtherName) {
woof,
moo
};
Rozszerza się być zwykłym enum w C++, ale jest wystarczający jako plik nagłówka narazić członków enum w Pythonie.
Używając %typemap(constcode)
możemy wprowadzić dodatkowe elementy do naszego modułu Pythona dla wyliczenia, ale musimy znać nazwę enum, aby to zrobić; Obiekt typu swiss dla SWIG jest taki, jak gdyby był to int
. Dlatego używamy odrobiny hackowania w naszym makrze PYTHON_ENUM
, aby zapisać nazwę wyliczenia w niestandardowej mapie typów.
%module test
%{
#include "test.h"
%}
%typemap(constcode) int {
PyObject *val = PyInt_FromLong(($type)($value));
SWIG_Python_SetConstant(d, "$1", val);
const char *name = "$typemap(enum_realname,$1_type)";
PyObject *e = PyDict_GetItemString(d, name);
if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
PyDict_SetItemString(e, "$value", val);
}
#define PYTHON_ENUM(x) \
%typemap(enum_realname) int "x"; \
%pythoncode %{ \
x = _test.x\
%} \
enum x
%include "test.h"
Spowoduje to utworzenie PyDict w module pośrednim dla każdego wyliczenia z parami klucz/wartość. Jest tam również pewna ilość kleju %pythoncode
, aby związać PyDict w module pośrednim z eksponowanym modułem. (Nie jestem pewien, jak odnieść się do modułu pośredniego po nazwie w nim, inne niż na stałe oznaczony jako _test - zmiana w razie potrzeby).
Wystarcza to, że mogę użyć go jako:
Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> print test.SomeOtherName
{'woof': 0, 'moo': 1}
>>> print test.TestName
{'foo': 1, 'bar': 2}
>>>
Wygląda więc na to, że trudność wynika z tego, że SWIG jest celowo celowy, wydaje się, że nie miał na myśli przeniesienia refleksji C/C++ do języków skryptowych, tylko generowania interfejsu. Wygląda na to, że będę musiał pójść z rozwiązaniem Marka Tolonena po prostu dlatego, że niewielu zrozumie twoje, chociaż jestem na krawędzi zrozumienia tego w tej chwili: D Dziękuję za przykład wypróbowania rzeczy z mapami. – unkulunkulu
@unkulunkulu - ogólnie SWIG stara się zrobić wszystko, co możliwe w C (lub C++), ale błądzenie poza tym wydaje się być trudniejsze. – Flexo
@Flexo Ładne rozwiązanie. Rozszerzyłem go nieco, aby zaimportować słownik, który obsługuje uzupełnianie kropek na klawiszach i zastąpił 'x = _test.x' za pomocą' x = dotdict (_test.x) 'i dodał'% pythoncode% {from dicts import dotdict% } 'przed makrem' PYTHON_ENUM'. –
- 1. Jak wyliczyć z enum w Objective-C?
- 2. Jak zaktualizować członków obiektu za pomocą dyktatury?
- 3. Jak wyliczyć członków obiektu COM w języku C#?
- 4. Czy można wyliczyć enum w C++?
- 5. Wiązanie biblioteki biblioteki C++ za pomocą SWIG
- 6. Jak rozwiązać typ klasy za pomocą enum
- 7. Jak odzyskać nazwę Enum za pomocą id?
- 8. Jak wyliczyć wątki w .NET za pomocą właściwości Nazwa?
- 9. Jak wygenerować interfejs między platformami za pomocą SWIG?
- 10. owijania C-enum w moduł Pythona z Swig
- 11. Jak mogę wyświetlić listę nieudokumentowanych członków za pomocą Sphinx/Autodoc?
- 12. Swift - za pomocą enum w instrukcji switch
- 13. Tworzenie modułów rozszerzających PHP C/C++ za pomocą SWIG
- 14. Wyliczyć metody obiektu COM (IDispatch) za pomocą ATL?
- 15. Obsługa wyjątków C++ w Javie za pomocą SWIG
- 16. Generowanie podpowiedzi typu Pythona za pomocą kodu SWIG
- 17. Jak wyliczyć przez JObject?
- 18. Jak wyliczyć uchwyt procesu?
- 19. Czy można uzyskać nazwy i wartości członków enum w D?
- 20. Funkcje członków dziedziczenia C++ za pomocą zmiennych statycznych
- 21. Dodawanie członków klasy do konkretnych lokalizacji za pomocą Roslyn?
- 22. Funkcje członków klasy tworzone za pomocą cech [polityki, faktycznie]
- 23. REST: uzyskiwanie dostępu do członków kolekcji za pomocą wielu identyfikatorów
- 24. Wykryto przeciek pamięci Swig/Pythona
- 25. Jak radzić sobie z unique_ptr z SWIG
- 26. Błędy SWIG z powodu dyrektywy preprocesora
- 27. Deserialize Enum z Xml za pomocą właściwości Value w C#
- 28. Laravel 5.0 IN Walidacja. Sprawdzanie poprawności za pomocą wartości ENUM
- 29. Wyliczyć wszystkie częściowe zamówienia
- 30. Wyliczyć kolejność w Clojure?
Tak, myślałem o czymś takim, ale odpowiedź zapewnia jakąś gotową do wykorzystania wzoru, dzięki. Czy możesz wyjaśnić nieco więcej na temat wspomnianego problemu 'sizeof'? Który kod może się dokładnie złamać, ponieważ nie rozumiem tego. – unkulunkulu
Usuwam tę część.To było coś, co rozważałem, próbując znaleźć implementację, ale po prostu wróciłem do tego i nie było to naprawdę problemem. –