summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generator/cppgenerator.cpp133
-rw-r--r--generator/cppgenerator.h2
-rw-r--r--libshiboken/conversions.h6
-rw-r--r--libshiboken/sbkenum.cpp149
-rw-r--r--libshiboken/sbkenum.h27
5 files changed, 144 insertions, 173 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp
index 77c34000..e7f0e428 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 645f63fd..4374eb5e 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 d4059b56..67e62792 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 f71a7476..34a4b772 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 447997e7..50ac9220 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