Fixed qt_metacall, now everything works as it should.

Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
          Lauro Moura <lauro.neto@openbossa.org>
This commit is contained in:
Hugo Parente Lima 2010-12-01 18:09:09 -02:00
commit 59b4f2b59d
4 changed files with 59 additions and 65 deletions

View file

@ -14,26 +14,26 @@ struct Converter<QVariant>
return true; return true;
} }
static QByteArray resolveMetaType(PyTypeObject* type, int &typeId) static const char* resolveMetaType(PyTypeObject* type, int* typeId)
{ {
if (PyObject_TypeCheck(type, &SbkObjectType_Type)) { if (PyObject_TypeCheck(type, &SbkObjectType_Type)) {
SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(type); SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(type);
QByteArray typeName(Shiboken::ObjectType::getOriginalName(sbkType)); const char* typeName = Shiboken::ObjectType::getOriginalName(sbkType);
bool valueType = !typeName.endsWith("*"); bool valueType = '*' != typeName[qstrlen(typeName) - 1];
// Do not convert user type of value // Do not convert user type of value
if (valueType && Shiboken::ObjectType::isUserType(type)) if (valueType && Shiboken::ObjectType::isUserType(type))
return QByteArray(); return 0;
int obTypeId = QMetaType::type(typeName); int obTypeId = QMetaType::type(typeName);
if (obTypeId) { if (obTypeId) {
typeId = obTypeId; *typeId = obTypeId;
return QByteArray(typeName); return typeName;
} }
// Do not resolve types to value type // Do not resolve types to value type
if (valueType) if (valueType)
return QByteArray(); return 0;
// find in base types // find in base types
if (type->tp_base) { if (type->tp_base) {
@ -41,14 +41,14 @@ struct Converter<QVariant>
} else if (type->tp_bases) { } else if (type->tp_bases) {
int size = PyTuple_GET_SIZE(type->tp_bases); int size = PyTuple_GET_SIZE(type->tp_bases);
for(int i=0; i < size; i++){ for(int i=0; i < size; i++){
QByteArray derivedName = resolveMetaType(reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(type->tp_bases, i)), typeId); const char* derivedName = resolveMetaType(reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(type->tp_bases, i)), typeId);
if (!derivedName.isEmpty()) if (derivedName)
return derivedName; return derivedName;
} }
} }
} }
typeId = 0; *typeId = 0;
return QByteArray(); return 0;
} }
static QVariant toCpp(PyObject* pyObj) static QVariant toCpp(PyObject* pyObj)
@ -87,22 +87,15 @@ struct Converter<QVariant>
} else { } else {
// a class supported by QVariant? // a class supported by QVariant?
if (Shiboken::Object::checkType(pyObj)) { if (Shiboken::Object::checkType(pyObj)) {
SbkObjectType* objType = reinterpret_cast<SbkObjectType*>(pyObj->ob_type); int typeCode;
int typeCode = 0; const char* typeName = resolveMetaType(pyObj->ob_type, &typeCode);
QByteArray typeName = resolveMetaType(reinterpret_cast<PyTypeObject*>(objType), typeCode);
if (typeCode) { if (typeCode && typeName) {
Shiboken::TypeResolver* tr = Shiboken::TypeResolver::get(typeName); Shiboken::TypeResolver* tr = Shiboken::TypeResolver::get(typeName);
void* data = 0; QVariant var(typeCode, (void*)0);
data = tr->toCpp(pyObj, &data, true); void* args[] = { var.data() };
if (typeName.endsWith("*")) { tr->toCpp(pyObj, args);
QVariant var(typeCode, &data); return var;
tr->deleteObject(data);
return var;
} else {
QVariant var(typeCode, data);
tr->deleteObject(data);
return var;
}
} }
} }
// Is a shiboken type not known by Qt // Is a shiboken type not known by Qt
@ -140,28 +133,25 @@ struct Converter<QVariant>
return QVariant(); return QVariant();
Shiboken::AutoDecRef element(PySequence_GetItem(list, 0)); Shiboken::AutoDecRef element(PySequence_GetItem(list, 0));
int typeId = 0; int typeId;
QByteArray typeName = resolveMetaType(element.cast<PyTypeObject*>(), typeId); const char* typeName = resolveMetaType(element.cast<PyTypeObject*>(), &typeId);
if (!typeName.isEmpty()) { if (typeName) {
QByteArray listTypeName = QByteArray("QList<"+typeName+">"); QByteArray listTypeName("QList<");
listTypeName += typeName;
listTypeName += '>';
typeId = QMetaType::type(listTypeName); typeId = QMetaType::type(listTypeName);
if (typeId > 0) { if (typeId > 0) {
Shiboken::TypeResolver* tr = Shiboken::TypeResolver::get(listTypeName); Shiboken::TypeResolver* tr = Shiboken::TypeResolver::get(listTypeName);
if (!tr) { if (!tr) {
qWarning() << "TypeResolver for :" << listTypeName << "not registered."; qWarning() << "TypeResolver for :" << listTypeName << "not registered.";
return QVariant();
} else { } else {
void *data = 0; QVariant var(typeId, (void*)0);
data = tr->toCpp(list, &data, true); void* args[] = { var.data(), 0 };
QVariant var(typeId, data); tr->toCpp(list, args);
tr->deleteObject(data);
return var; return var;
} }
} else {
return QVariant();
} }
} }
return QVariant(); return QVariant();
} }

View file

@ -98,29 +98,26 @@ void functionFree(void *self)
PyObject* functionCall(PyObject* self, PyObject* args, PyObject* kw) PyObject* functionCall(PyObject* self, PyObject* args, PyObject* kw)
{ {
QGenericArgument gArgs[10]; static Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get("QVariant");
PySideMetaFunction* function = reinterpret_cast<PySideMetaFunction*>(self);
QList<QVariant*> vArgs;
QMetaMethod method = function->d->method;
QList<QByteArray> pTypes = method.parameterTypes();
int numArgs = pTypes.size();
Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get("QVariant");
Q_ASSERT(typeResolver); Q_ASSERT(typeResolver);
for(int i=0; i < numArgs; i++) {
QVariant *vArg; QGenericArgument gArgs[10];
QVariant vArgs[10];
PySideMetaFunction* function = reinterpret_cast<PySideMetaFunction*>(self);
QMetaMethod method = function->d->method;
int argsGiven = method.parameterTypes().size();
for (int i = 0; i < argsGiven; ++i) {
Shiboken::AutoDecRef pyArg(PySequence_GetItem(args, i)); Shiboken::AutoDecRef pyArg(PySequence_GetItem(args, i));
typeResolver->toCpp(pyArg, (void**)&vArg, true); gArgs[i] = Q_ARG(QVariant, vArgs[i]);
vArgs.append(vArg); void* v[1] = { &vArgs[i] };
gArgs[i] = Q_ARG(QVariant, *vArg); typeResolver->toCpp(pyArg, v);
} }
QVariant retVariant; QVariant retVariant;
QGenericReturnArgument returnValue = Q_RETURN_ARG(QVariant, retVariant); QGenericReturnArgument returnValue = Q_RETURN_ARG(QVariant, retVariant);
method.invoke(function->d->qobject, returnValue, gArgs[0], gArgs[1], gArgs[2], gArgs[3], gArgs[4], gArgs[5], gArgs[6], gArgs[7], gArgs[8], gArgs[9]); method.invoke(function->d->qobject, returnValue, gArgs[0], gArgs[1], gArgs[2], gArgs[3], gArgs[4], gArgs[5], gArgs[6], gArgs[7], gArgs[8], gArgs[9]);
while(!vArgs.isEmpty())
delete vArgs.takeFirst();
if (retVariant.isValid()) if (retVariant.isValid())
return typeResolver->toPython(&retVariant); return typeResolver->toPython(&retVariant);

View file

@ -70,9 +70,17 @@ PyObjectWrapper::PyObjectWrapper(const PyObjectWrapper &other)
PyObjectWrapper::~PyObjectWrapper() PyObjectWrapper::~PyObjectWrapper()
{ {
Shiboken::GilState gil;
Py_DECREF(m_me); Py_DECREF(m_me);
} }
PyObjectWrapper& PyObjectWrapper::operator=(const PySide::PyObjectWrapper& other)
{
Py_INCREF(other.m_me);
Py_DECREF(m_me);
m_me = other.m_me;
return *this;
}
PyObjectWrapper::operator PyObject*() const PyObjectWrapper::operator PyObject*() const
{ {
@ -179,24 +187,26 @@ static bool emitNormalSignal(QObject* source, int signalIndex, const char* signa
{ {
Shiboken::AutoDecRef sequence(PySequence_Fast(args, 0)); Shiboken::AutoDecRef sequence(PySequence_Fast(args, 0));
int argsGiven = PySequence_Fast_GET_SIZE(sequence.object()); int argsGiven = PySequence_Fast_GET_SIZE(sequence.object());
if (argsGiven > argTypes.count()) { if (argsGiven > argTypes.count()) {
PyErr_Format(PyExc_TypeError, "%s only accepts %d arguments, %d given!", signal, argTypes.count(), argsGiven); PyErr_Format(PyExc_TypeError, "%s only accepts %d arguments, %d given!", signal, argTypes.count(), argsGiven);
return false; return false;
} }
void** signalArgs = new void*[argsGiven+1]; QVariant* signalValues = new QVariant[argsGiven];
void** signalValues = new void*[argsGiven]; void** signalArgs = new void*[argsGiven + 1];
signalArgs[0] = 0; signalArgs[0] = 0;
int i; int i;
for (i = 0; i < argsGiven; ++i) { for (i = 0; i < argsGiven; ++i) {
Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get(qPrintable(argTypes[i])); const char* typeName = argTypes[i].toAscii().constData();
Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get(typeName);
if (typeResolver) { if (typeResolver) {
typeResolver->toCpp(PySequence_Fast_GET_ITEM(sequence.object(), i), &signalValues[i], true); int typeId = QMetaType::type(typeName);
if (Shiboken::TypeResolver::getType(qPrintable(argTypes[i])) == Shiboken::TypeResolver::ObjectType) if (Shiboken::TypeResolver::getType(typeName) == Shiboken::TypeResolver::ValueType)
signalArgs[i+1] = &signalValues[i]; signalValues[i] = QVariant(typeId, (void*) 0);
else signalArgs[i+1] = signalValues[i].data();
signalArgs[i+1] = signalValues[i]; typeResolver->toCpp(PySequence_Fast_GET_ITEM(sequence.object(), i), &signalArgs[i+1]);
} else { } else {
PyErr_Format(PyExc_TypeError, "Unknown type used to emit a signal: %s", qPrintable(argTypes[i])); PyErr_Format(PyExc_TypeError, "Unknown type used to emit a signal: %s", qPrintable(argTypes[i]));
break; break;
@ -207,10 +217,6 @@ static bool emitNormalSignal(QObject* source, int signalIndex, const char* signa
if (ok) if (ok)
QMetaObject::activate(source, signalIndex, signalArgs); QMetaObject::activate(source, signalIndex, signalArgs);
//cleanup memory
for (int j = 0; j < i; ++j)
Shiboken::TypeResolver::get(qPrintable(argTypes[j]))->deleteObject(signalArgs[j+1]);
delete[] signalArgs; delete[] signalArgs;
delete[] signalValues; delete[] signalValues;

View file

@ -43,6 +43,7 @@ public:
PyObjectWrapper(const PyObjectWrapper &other); PyObjectWrapper(const PyObjectWrapper &other);
~PyObjectWrapper(); ~PyObjectWrapper();
operator PyObject*() const; operator PyObject*() const;
PyObjectWrapper& operator=(const PyObjectWrapper &other);
private: private:
PyObject* m_me; PyObject* m_me;
void* m_data; //future void* m_data; //future