diff options
-rw-r--r-- | generator/cppgenerator.cpp | 133 | ||||
-rw-r--r-- | generator/cppgenerator.h | 2 | ||||
-rw-r--r-- | libshiboken/conversions.h | 6 | ||||
-rw-r--r-- | libshiboken/sbkenum.cpp | 149 | ||||
-rw-r--r-- | libshiboken/sbkenum.h | 27 |
5 files changed, 144 insertions, 173 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 77c34000f..e7f0e4286 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -431,8 +431,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl s << endl; } - writeEnumDefinition(s, cppEnum); - if (hasFlags) { // Write Enum as Flags definition (at the moment used only by QFlags<enum>) writeFlagsDefinition(s, cppEnum); @@ -2927,13 +2925,18 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << cppEnum->name() << endl; if (!cppEnum->isAnonymous()) { - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = &" << cpythonTypeName(cppEnum->typeEntry()) << ';' << endl; - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl; + s << INDENT << "PyTypeObject* " << cpythonName << " = Shiboken::Enum::newType(\"" << cppEnum->name() << "\");" << endl; + + if (cppEnum->typeEntry()->flags()) + s << INDENT << cpythonName << "->tp_as_number = &" << cpythonName << "_as_number;" << endl; + + s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = " << cpythonName << ';' << endl; + s << INDENT << "if (PyType_Ready(" << cpythonName << ") < 0)" << endl; s << INDENT << INDENT << "return;" << endl; s << INDENT << addFunction << endl; s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; - s << "((PyObject*)&" << cpythonName << "_Type));" << endl << endl; + s << "((PyObject*)" << cpythonName << "));" << endl << endl; FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); if (flags) { @@ -2970,13 +2973,12 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu #endif bool shouldDecrefNumber = false; - QString enumItemText = "enum_item"; + QString enumItemText = "enumItem"; if (!cppEnum->isAnonymous()) { - s << INDENT << "enum_item = Shiboken::SbkEnumObject_New(&"; - s << cpythonName << "_Type," << enumValueText << ", \""; - s << enumValue->name() << "\");" << endl; + s << INDENT << "enumItem = Shiboken::Enum::newItem(" << cpythonName << "," << enumValueText; + s << ", \"" << enumValue->name() << "\");" << endl; } else if (cppEnum->enclosingClass()) { - s << INDENT << "enum_item = PyInt_FromLong(" << enumValueText << ");" << endl; + s << INDENT << "enumItem = PyInt_FromLong(" << enumValueText << ");" << endl; shouldDecrefNumber = true; } else { enumItemText = enumValueText; @@ -2984,13 +2986,13 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << INDENT << addFunction << '"' << enumValue->name() << "\", " << enumItemText << ");" << endl; if (shouldDecrefNumber) - s << INDENT << "Py_DECREF(enum_item);" << endl; + s << INDENT << "Py_DECREF(enumItem);" << endl; if (!cppEnum->isAnonymous()) { - s << INDENT << "Py_DECREF(enum_item);" << endl; - s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict,"; - s << '"' << enumValue->name() << "\", enum_item);" << endl; - s << INDENT << "Py_DECREF(enum_item);" << endl; + s << INDENT << "Py_DECREF(enumItem);" << endl; + s << INDENT << "PyDict_SetItemString(" << cpythonName << "->tp_dict,"; + s << '"' << enumValue->name() << "\", enumItem);" << endl; + s << INDENT << "Py_DECREF(enumItem);" << endl; } } @@ -3003,7 +3005,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu } - s << endl; + s << INDENT << "// end of enum " << cppEnum->name() << endl << endl; } void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) @@ -3056,98 +3058,6 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC s << endl; } -void CppGenerator::writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - s << "static PyObject* "; - s << cpythonName << "_New(PyTypeObject* type, PyObject* args, PyObject* kwds)" << endl; - s << '{' << endl; - s << INDENT << "int item_value = 0;" << endl; - s << INDENT << "if (!PyArg_ParseTuple(args, \"|i:__new__\", &item_value))" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return 0;" << endl; - } - s << INDENT << "PyObject* self = Shiboken::SbkEnumObject_New(type, item_value);" << endl << endl; - s << INDENT << "if (!self)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return 0;" << endl; - } - s << INDENT << "return self;" << endl << '}' << endl; -} - -void CppGenerator::writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - QString tp_as_number("0"); - if (cppEnum->typeEntry()->flags()) - tp_as_number = QString("&%1_as_number").arg(cpythonName); - - - s << "static PyGetSetDef " << cpythonName << "_getsetlist[] = {" << endl; - s << INDENT << "{const_cast<char*>(\"name\"), (getter)Shiboken::SbkEnumObject_name}," << endl; - s << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - - QString newFunc = cpythonName + "_New"; - - s << "// forward declaration of new function" << endl; - s << "static PyObject* " << newFunc << "(PyTypeObject*, PyObject*, PyObject*);" << endl << endl; - - s << "static PyTypeObject " << cpythonName << "_Type = {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkEnumType_Type)" << endl; - s << INDENT << "/*ob_size*/ 0," << endl; - s << INDENT << "/*tp_name*/ \"" << cppEnum->name() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(Shiboken::SbkEnumObject)," << endl; - s << INDENT << "/*tp_itemsize*/ 0," << endl; - s << INDENT << "/*tp_dealloc*/ 0," << endl; - s << INDENT << "/*tp_print*/ 0," << endl; - s << INDENT << "/*tp_getattr*/ 0," << endl; - s << INDENT << "/*tp_setattr*/ 0," << endl; - s << INDENT << "/*tp_compare*/ 0," << endl; - s << INDENT << "/*tp_repr*/ Shiboken::SbkEnumObject_repr," << endl; - s << INDENT << "/*tp_as_number*/ " << tp_as_number << ',' << endl; - s << INDENT << "/*tp_as_sequence*/ 0," << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; - s << INDENT << "/*tp_hash*/ 0," << endl; - s << INDENT << "/*tp_call*/ 0," << endl; - s << INDENT << "/*tp_str*/ Shiboken::SbkEnumObject_repr," << endl; - s << INDENT << "/*tp_getattro*/ 0," << endl; - s << INDENT << "/*tp_setattro*/ 0," << endl; - s << INDENT << "/*tp_as_buffer*/ 0," << endl; - s << INDENT << "/*tp_flags*/ Py_TPFLAGS_DEFAULT," << endl; - s << INDENT << "/*tp_doc*/ 0," << endl; - s << INDENT << "/*tp_traverse*/ 0," << endl; - s << INDENT << "/*tp_clear*/ 0," << endl; - s << INDENT << "/*tp_richcompare*/ 0," << endl; - s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; - s << INDENT << "/*tp_iter*/ 0," << endl; - s << INDENT << "/*tp_iternext*/ 0," << endl; - s << INDENT << "/*tp_methods*/ 0," << endl; - s << INDENT << "/*tp_members*/ 0," << endl; - s << INDENT << "/*tp_getset*/ " << cpythonName << "_getsetlist," << endl; - s << INDENT << "/*tp_base*/ &PyInt_Type," << endl; - s << INDENT << "/*tp_dict*/ 0," << endl; - s << INDENT << "/*tp_descr_get*/ 0," << endl; - s << INDENT << "/*tp_descr_set*/ 0," << endl; - s << INDENT << "/*tp_dictoffset*/ 0," << endl; - s << INDENT << "/*tp_init*/ 0," << endl; - s << INDENT << "/*tp_alloc*/ 0," << endl; - s << INDENT << "/*tp_new*/ " << newFunc << ',' << endl; - s << INDENT << "/*tp_free*/ 0," << endl; - s << INDENT << "/*tp_is_gc*/ 0," << endl; - s << INDENT << "/*tp_bases*/ 0," << endl; - s << INDENT << "/*tp_mro*/ 0," << endl; - s << INDENT << "/*tp_cache*/ 0," << endl; - s << INDENT << "/*tp_subclasses*/ 0," << endl; - s << INDENT << "/*tp_weaklist*/ 0" << endl; - s << "};" << endl << endl; - - writeEnumNewMethod(s, cppEnum); - s << endl; -} - void CppGenerator::writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum) { writeFlagsBinaryOperator(s, cppEnum, "and", "&"); @@ -3226,7 +3136,7 @@ void CppGenerator::writeFlagsDefinition(QTextStream& s, const AbstractMetaEnum* s << INDENT << "/*tp_setattr*/ 0," << endl; s << INDENT << "/*tp_compare*/ 0," << endl; s << INDENT << "/*tp_repr*/ 0," << endl; - s << INDENT << "/*tp_as_number*/ " << enumName << "_Type.tp_as_number," << endl; + s << INDENT << "/*tp_as_number*/ &" << enumName << "_as_number," << endl; s << INDENT << "/*tp_as_sequence*/ 0," << endl; s << INDENT << "/*tp_as_mapping*/ 0," << endl; s << INDENT << "/*tp_hash*/ 0," << endl; @@ -3368,7 +3278,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (!metaClass->enums().isEmpty()) { s << INDENT << "// Initialize enums" << endl; - s << INDENT << "PyObject* enum_item;" << endl << endl; + s << INDENT << "PyObject* enumItem;" << endl << endl; } foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { @@ -3703,7 +3613,6 @@ void CppGenerator::finishGeneration() foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; - writeEnumDefinition(s, cppEnum); s << endl; } @@ -3781,7 +3690,7 @@ void CppGenerator::finishGeneration() if (!globalEnums().isEmpty()) { s << INDENT << "// Initialize enums" << endl; - s << INDENT << "PyObject* enum_item;" << endl << endl; + s << INDENT << "PyObject* enumItem;" << endl << endl; } foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 645f63fd2..4374eb5e4 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -145,8 +145,6 @@ private: void writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass); void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass); - void writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* metaEnum); void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); void writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index d4059b565..67e627926 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -491,11 +491,11 @@ struct EnumConverter static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CppEnum*>(cppobj)); } static inline PyObject* toPython(CppEnum cppenum) { - return SbkEnumObject_New(SbkType<CppEnum>(), (long) cppenum); + return Shiboken::Enum::newItem(Shiboken::SbkType<CppEnum>(), (long) cppenum); } - static inline CppEnum toCpp(PyObject* pyobj) + static inline CppEnum toCpp(PyObject* pyObj) { - return (CppEnum) reinterpret_cast<SbkEnumObject*>(pyobj)->ob_ival; + return (CppEnum) Shiboken::Enum::getValue(pyObj);; } }; diff --git a/libshiboken/sbkenum.cpp b/libshiboken/sbkenum.cpp index f71a74769..34a4b7729 100644 --- a/libshiboken/sbkenum.cpp +++ b/libshiboken/sbkenum.cpp @@ -21,12 +21,52 @@ */ #include "sbkenum.h" +#include <cstring> +#include <list> +#include "sbkdbg.h" +#include "autodecref.h" -namespace Shiboken +extern "C" { -extern "C" +struct SbkEnumObject +{ + PyObject_HEAD + long ob_ival; + PyObject* ob_name; +}; + +static PyObject* SbkEnumObject_repr(PyObject* self) +{ + return PyString_FromFormat("<enum-item %s.%s (%ld)>", + self->ob_type->tp_name, + PyString_AS_STRING(((SbkEnumObject*)self)->ob_name), + ((SbkEnumObject*)self)->ob_ival); +} + +static PyObject* SbkEnumObject_name(PyObject* self, void*) { + Py_INCREF(((SbkEnumObject*)self)->ob_name); + return ((SbkEnumObject*)self)->ob_name; +} + +static PyObject* SbkEnum_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + int itemValue = 0; + if (!PyArg_ParseTuple(args, "|i:__new__", &itemValue)) + return 0; + + SbkEnumObject* self = PyObject_New(SbkEnumObject, type); + if (!self) + return 0; + self->ob_ival = itemValue; + return reinterpret_cast<PyObject*>(self); +} + +static PyGetSetDef SbkEnumGetSetList[] = { + {const_cast<char*>("name"), &SbkEnumObject_name}, + {0} // Sentinel +}; PyTypeObject SbkEnumType_Type = { PyObject_HEAD_INIT(0) @@ -77,65 +117,98 @@ PyTypeObject SbkEnumType_Type = { /*tp_weaklist*/ 0 }; -} +} // extern "C" + +namespace Shiboken { -PyObject* -SbkEnumObject_New(PyTypeObject *type, long item_value, PyObject* item_name) +class DeclaredEnumTypes { - if (!item_name) - item_name = PyString_FromString(""); - SbkEnumObject* enum_obj = PyObject_New(SbkEnumObject, type); - enum_obj->ob_name = item_name; - enum_obj->ob_ival = item_value; - return (PyObject*) enum_obj; -} +public: + DeclaredEnumTypes(); + ~DeclaredEnumTypes(); + static DeclaredEnumTypes& instance(); + void addEnumType(PyTypeObject* type); +private: + DeclaredEnumTypes(const DeclaredEnumTypes&); + DeclaredEnumTypes& operator=(const DeclaredEnumTypes&); + std::list<PyTypeObject*> m_enumTypes; +}; + +namespace Enum { -PyObject* -SbkEnumObject_New(PyTypeObject *type, long item_value, const char* item_name) +PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName) { - PyObject* py_item_name = 0; - if (item_name) - py_item_name = PyString_FromString(item_name); + if (!itemName) + itemName = ""; + PyObject* pyItemName = PyString_FromString(itemName); - PyObject* enum_obj = SbkEnumObject_New(type, item_value, py_item_name); - if (!enum_obj) { - Py_XDECREF(py_item_name); + SbkEnumObject* enumObj = PyObject_New(SbkEnumObject, enumType); + if (!enumObj) { + Py_XDECREF(pyItemName); return 0; } - if (item_name) { - PyObject* values = PyDict_GetItemString(type->tp_dict, const_cast<char*>("values")); + enumObj->ob_name = pyItemName; + enumObj->ob_ival = itemValue; + if (itemName) { + PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast<char*>("values")); if (!values) { values = PyDict_New(); - PyDict_SetItemString(type->tp_dict, const_cast<char*>("values"), values); + PyDict_SetItemString(enumType->tp_dict, const_cast<char*>("values"), values); Py_DECREF(values); // ^ values still alive, because setitemstring incref it } - PyDict_SetItemString(values, item_name, enum_obj); + PyDict_SetItemString(values, itemName, reinterpret_cast<PyObject*>(enumObj)); } - return enum_obj; + return reinterpret_cast<PyObject*>(enumObj); } -extern "C" +PyTypeObject* newType(const char* name) { + PyTypeObject* type = new PyTypeObject; + ::memset(type, 0, sizeof(PyTypeObject)); + type->ob_type = &SbkEnumType_Type; + type->tp_basicsize = sizeof(SbkEnumObject); + type->tp_repr = &SbkEnumObject_repr; + type->tp_str = &SbkEnumObject_repr; + type->tp_flags = Py_TPFLAGS_DEFAULT; + type->tp_base = &PyInt_Type; + type->tp_name = name; + type->tp_getset = SbkEnumGetSetList; + type->tp_new = SbkEnum_tp_new; + + DeclaredEnumTypes::instance().addEnumType(type); + return type; +} -PyObject* -SbkEnumObject_repr(PyObject* self) +long int getValue(PyObject* enumItem) { - return PyString_FromFormat("<enum-item %s.%s (%ld)>", - self->ob_type->tp_name, - PyString_AS_STRING(((SbkEnumObject*)self)->ob_name), - ((SbkEnumObject*)self)->ob_ival); + return reinterpret_cast<SbkEnumObject*>(enumItem)->ob_ival; } -PyObject* -SbkEnumObject_name(PyObject* self) +} // namespace Enum + +DeclaredEnumTypes& DeclaredEnumTypes::instance() { - Py_INCREF(((SbkEnumObject*)self)->ob_name); - return ((SbkEnumObject*)self)->ob_name; + static DeclaredEnumTypes me; + return me; } -} // extern "C" +DeclaredEnumTypes::DeclaredEnumTypes() +{ +} -} // namespace Shiboken +DeclaredEnumTypes::~DeclaredEnumTypes() +{ + std::list<PyTypeObject*>::const_iterator it = m_enumTypes.begin(); + for (; it != m_enumTypes.end(); ++it) + delete *it; + m_enumTypes.clear(); +} +void DeclaredEnumTypes::addEnumType(PyTypeObject* type) +{ + m_enumTypes.push_back(type); +} + +} diff --git a/libshiboken/sbkenum.h b/libshiboken/sbkenum.h index 447997e75..50ac9220a 100644 --- a/libshiboken/sbkenum.h +++ b/libshiboken/sbkenum.h @@ -26,36 +26,27 @@ #include <Python.h> #include "shibokenmacros.h" -namespace Shiboken -{ - extern "C" { -typedef struct { - PyObject_HEAD - long ob_ival; - PyObject* ob_name; -} SbkEnumObject; - extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type; -LIBSHIBOKEN_API PyObject* SbkEnumObject_repr(PyObject* self); -LIBSHIBOKEN_API PyObject* SbkEnumObject_name(PyObject* self); - } // extern "C" +namespace Shiboken +{ + inline bool isShibokenEnum(PyObject* pyObj) { return pyObj->ob_type->ob_type == &SbkEnumType_Type; } -LIBSHIBOKEN_API PyObject* SbkEnumObject_New(PyTypeObject *instanceType, - long item_value, - const char* item_name); -LIBSHIBOKEN_API PyObject* SbkEnumObject_New(PyTypeObject *instanceType, - long item_value, - PyObject* item_name = 0); +namespace Enum +{ + LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0); + LIBSHIBOKEN_API PyTypeObject* newType(const char* name); + LIBSHIBOKEN_API long getValue(PyObject* enumItem); +} } // namespace Shiboken |