QSA-interest Archive, February 2006
Re: QSA crash when calling a slot that returns QVariant
Message 1 in thread
Hi
Thanks for the fix... that helped me a lot.
But QSA still crashes if a function returns an invalid QVariant like this:
return QVariant();
I wanted to use this if the slot-function did not succeed.
Right now I have to work around this problem this way:
return QVariant( QString("") );
Will this be fixed in QSA 1.2.1, too?
Greetings
Jens
Am Freitag, 20. Januar 2006 03:09 schrieb Joel Nordell:
> Hello,
>
> I believe I have found a bug in QSA 1.2.0 w/ Qt 4.1.0. I'm porting a
> large project from Qt 3 to Qt 4, and really giving QSA a good
> workout! :)
>
> QSA seems to crash whenever a script calls a slot that returns a
> QVariant. I've attached an example program that illustrates this.
>
> I have also figured out a potential fix. In the file src/kernel/
> quickobjects.cpp, change the qsa_default_value function to this:
>
> ---
> static void *qsa_default_value(QSASlotCaching *caching, const
> QSATypeInfo &ti)
> {
> const QVariant *v = caching->variants(QVariant::Type(ti.id));
> void *const_data = (void *) v->constData();
>
> if (v->type() == QVariant::Invalid) {
> if (ti.name == "QList<int>")
> return caching->intlists(QList<int>());
> else if (ti.name == "QObjectList")
> return caching->qobjectlists(QObjectList());
> else if (ti.name == "QVariant") // <--- These two lines fix
> the crash
> return caching->variants(QVariant());
> else if (ti.name.count('*') == 0 && ti.name.length() > 0)
> return 0;
> }
>
> return const_data;
> }
> ---
>
> Note the added condition to checki if ti.name == "QVariant". That
> seems to do the trick.
>
> Joel Nordell
> Software Engineer
> ONEAC Corp.
>
> ïï
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
Message 2 in thread
Hi Jens,
Here is my patch to fix the crash on return of an invalid QVariant--
In src/kernel/quickobjects.cpp, in the convert_qt2qsa function,
change this:
} else if (ti.name == "QVariant") {
// We could have casted directly, but we choose to use
// the common code path
QVariant *var = ((QVariant *) value);
return qsa_script_variant(ip, var->type(), (void *) var-
>constData());
to this:
} else if (ti.name == "QVariant") {
// We could have casted directly, but we choose to use
// the common code path
QVariant *var = ((QVariant *) value);
if (var->isNull()) return env->createUndefined();
else return qsa_script_variant(ip, var->type(), (void *) var-
>constData());
I've been sending these patches to Gunnar at TrollTech, so hopefully
they will be included in QSA 1.2.1.
-Joel
On Feb 7, 2006, at 7:40 AM, Jens G. wrote:
> Hi
> Thanks for the fix... that helped me a lot.
>
> But QSA still crashes if a function returns an invalid QVariant
> like this:
>
> return QVariant();
>
> I wanted to use this if the slot-function did not succeed.
> Right now I have to work around this problem this way:
>
> return QVariant( QString("") );
>
> Will this be fixed in QSA 1.2.1, too?
>
> Greetings
> Jens
>
> Am Freitag, 20. Januar 2006 03:09 schrieb Joel Nordell:
>> Hello,
>>
>> I believe I have found a bug in QSA 1.2.0 w/ Qt 4.1.0. I'm porting a
>> large project from Qt 3 to Qt 4, and really giving QSA a good
>> workout! :)
>>
>> QSA seems to crash whenever a script calls a slot that returns a
>> QVariant. I've attached an example program that illustrates this.
>>
>> I have also figured out a potential fix. In the file src/kernel/
>> quickobjects.cpp, change the qsa_default_value function to this:
>>
>> ---
>> static void *qsa_default_value(QSASlotCaching *caching, const
>> QSATypeInfo &ti)
>> {
>> const QVariant *v = caching->variants(QVariant::Type(ti.id));
>> void *const_data = (void *) v->constData();
>>
>> if (v->type() == QVariant::Invalid) {
>> if (ti.name == "QList<int>")
>> return caching->intlists(QList<int>());
>> else if (ti.name == "QObjectList")
>> return caching->qobjectlists(QObjectList());
>> else if (ti.name == "QVariant") // <--- These two lines fix
>> the crash
>> return caching->variants(QVariant());
>> else if (ti.name.count('*') == 0 && ti.name.length() > 0)
>> return 0;
>> }
>>
>> return const_data;
>> }
>> ---
>>
>> Note the added condition to checki if ti.name == "QVariant". That
>> seems to do the trick.
>>
>> Joel Nordell
>> Software Engineer
>> ONEAC Corp.
>>
>
> To unsubscribe - send "unsubscribe" in the subject to qsa-interest-
> request@xxxxxxxxxxxxx
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
Message 3 in thread
I am looking for a way to get notified when the interpreter has
finished running. I would assume there to be a signal "stopped" or
"terminated" in QSInterpreter, but unfortunately there isn't any.
So is the only way to poll isRunning() ?
Peter
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
Message 4 in thread
Peter Koch wrote:
> I am looking for a way to get notified when the interpreter has
> finished running. I would assume there to be a signal "stopped" or
> "terminated" in QSInterpreter, but unfortunately there isn't any.
>
> So is the only way to poll isRunning() ?
For normal execution you could trigger this yourself, since you call
QSInterpterer::evaluate() and QSInterpreter::call(). In your class you
could encapsulate those calls with:
emit interpreterStarted();
interpreter.evaluate(code);
emit interpreterStopped();
and similar for call(). This would give all execution, except when the
interpreter is running a slot connection.
I can note this down as a suggestion for future versions though.
-
Best regards,
Gunnar
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
Message 5 in thread
1. When an object is created in a QSObjectFactory, should I assign a
parent object to it, or will QSA do that and therefore care for
deleting the object when it is no longer needed?
2. When my object has a slot for creating subobjects (a factory-slot),
the same question: Should my object take care for deleting the
subobject, or is the creating object responsible for it?
EXAMPLE
-------------------------
Script:
function foo()
{
var obj = new MyObject;
{
sub1 = obj.createSubObject();
sub2 = new MyObject;
}
// will sub1 / sub2 have been deleted here by interpreter?
}
// will obj / sub1 / sub2 have been deleted here by interpreter?
----------------------------
C++ Class:
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject(QObject *parent) : QObject(parent)
{
setObjectName("MyObject");
}
public slots:
MyObject* createSubObject()
{
return new MyObject(this);
}
};
-----------------------------
Factory:
QObject* MyObjectFactory::create(
const QString& name, const QVariantLoist& args, QObject* context)
{
if (name == "MyObject")
return new MyObject(/* what parent here: 0, context or this? */);
return 0;
}
I hope somebody can shed a light on this.
Thanks,
Peter
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
Message 6 in thread
Here are the results as far as I figured out with the test below.
Somebody may correct me if my interpretation is wrong:
1. Objects created by a "factory slot" stay in the ownership of the
creating class.
2. Opjects created with a QSObjectFactory (new ... in the script) are
owned by the interpreter who will care for deleting them.
Here is my test with the results:
--------------------------------8<--------------------------------
main.h:
#ifndef MAIN_H
#define MAIN_H
#include <qsinterpreter.h>
#include <qsobjectfactory.h>
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name WRITE setName READ name)
public:
MyClass(QObject* parent = 0) : QObject(parent) { setObjectName("MyClass"); }
~MyClass() { qDebug(QString("destruct %1").arg(m_name).toAscii()); }
public slots:
QString name() const { return m_name; }
void setName(const QString& name) { m_name = name; }
MyClass* create() { return new MyClass(this); }
private:
QString m_name;
};
class Factory : public QSObjectFactory
{
public:
Factory() { registerClass("MyClass", &MyClass::staticMetaObject); }
QObject* create(const QString& name, const QVariantList& arguments, QObject *context)
{
if (name == "MyClass") return new MyClass(context);
throwError("Class "+name+" not implemented.");
return 0;
}
};
#endif
--------------------------------8<--------------------------------
main.c:
#include <QtCore/QCoreApplication>
#include "main.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSInterpreter qsi;
qsi.addObjectFactory(new Factory);
qsi.evaluate(
"function foo()\n"
"{\n"
" debug('begin foo');\n"
" var obj = new MyClass;\n"
" obj.name = 'obj';\n"
" for (var i = 0; i < 3; i++) {\n"
" debug('begin block '+i);\n"
" var sub1 = new MyClass;\n"
" sub1.name = 'sub1-'+i;\n"
" var sub2 = obj.create();\n"
" sub2.name = 'sub2-'+i;\n"
" debug('end block '+i);\n"
" }"
" debug('end foo');\n"
"}\n"
"\n"
"debug('call foo');\n"
"foo();\n"
"debug('returned from foo');\n"
);
qDebug("evaluate finished");
}
--------------------------------8<--------------------------------
output:
---> call foo
---> begin foo
---> begin block 0
---> end block 0
---> begin block 1
destruct sub1-0
---> end block 1
---> begin block 2
destruct sub1-1
---> end block 2
---> end foo
destruct sub1-2
destruct obj
destruct sub2-0
destruct sub2-1
destruct sub2-2
---> returned from foo
evaluate finished
--------------------------------8<--------------------------------
Peter
> 1. When an object is created in a QSObjectFactory, should I assign a
> parent object to it, or will QSA do that and therefore care for
> deleting the object when it is no longer needed?
> 2. When my object has a slot for creating subobjects (a factory-slot),
> the same question: Should my object take care for deleting the
> subobject, or is the creating object responsible for it?
> EXAMPLE
> -------------------------
> Script:
> function foo()
> {
> var obj = new MyObject;
> {
> sub1 = obj.createSubObject();
> sub2 = new MyObject;
> }
> // will sub1 / sub2 have been deleted here by interpreter?
> }
> // will obj / sub1 / sub2 have been deleted here by interpreter?
> ----------------------------
> C++ Class:
> class MyObject : public QObject
> {
> Q_OBJECT
> public:
> MyObject(QObject *parent) : QObject(parent)
> {
> setObjectName("MyObject");
> }
> public slots:
> MyObject* createSubObject()
> {
> return new MyObject(this);
> }
> };
> -----------------------------
> Factory:
> QObject* MyObjectFactory::create(
> const QString& name, const QVariantLoist& args, QObject* context)
> {
> if (name == "MyObject")
> return new MyObject(/* what parent here: 0, context or this? */);
> return 0;
> }
> I hope somebody can shed a light on this.
> Thanks,
> Peter
> To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx
Message 7 in thread
Peter Koch wrote:
> Here are the results as far as I figured out with the test below.
> Somebody may correct me if my interpretation is wrong:
>
> 1. Objects created by a "factory slot" stay in the ownership of the
> creating class.
>
> 2. Opjects created with a QSObjectFactory (new ... in the script) are
> owned by the interpreter who will care for deleting them.
Unless the object has a parent at object shutdown time, in which case
ownership is transferred to the parent automatically cleaned when the
parent is cleaned.
-
Gunnar
To unsubscribe - send "unsubscribe" in the subject to qsa-interest-request@xxxxxxxxxxxxx