QSA-interest Archive, October 2005
automatic casting of variables to its superclass-type
Message 1 in thread
Hi trolls
This could be a feature-request for the next QSA ( but hopefully it is already
possible with 1.2.0).
After working with QSA for some time now I thought about the possibility of
wrapping whole C++-libraries to be able to use them with QScripts. Together
with the Qt-Plugin-System it would be possible to give an application new
functions of external libraries by simply adding a new wrapper-plugin.
I have already wrote a source-code-generator to be able to simply choose
the include-files of the library to create wrapper-classes for each
library-class. But now I´m really stuck.
The problem is, that a slot like "void setMyClass(MySuperClass*)" cannot be
used in a script with objects from classes which inherit MySuperClass.
(which is possible in C++)
With the class-definitions from the end of this email, I would like to run a
script like this:
var C = new MyClass();
var useC = new MyUseClass();
useC.setMyClass( C );
What I did:
I wrapped all classes of the external library and registerd these
wrapper-classes in MyQSObjectFactory.
The constructor of MyQSObjectFactory includes
qRegisterMetaType<MySuperClass>("MySuperClass");
qRegisterMetaType<MyClass>("MySuperClass");
qRegisterMetaType<MyClass>("MyUseClass");
,too.
The wrapper-classes are useable in QScripts as long as I call them with
objects of desired class-Type.
This would work:
var superC = new MySuperClass();
var useC = new MyUseClass();
useC.setMyClass(superC);
But this does not work:
var C = new MySuperClass();
var useC = new MyUseClass();
useC.setMyClass(C);
Qt´s metasystem should be able to figure out if the desired class is a
superclass of the delivered one and could accept the variable.
I wonder why QVariant does not cast automatically.
What can I do ?
Greetings
Jens
======================================
class MySuperClass
{
public slots:
virtual void wrapSuperFunc1();
virtual void wrapSuperFunc2();
}
Q_DECLARE_METATYPE(MySuperClass)
class MyClass : public MySuperClass
{
public slots:
void wrapFunc1();
void wrapFunc2();
}
Q_DECLARE_METATYPE(MyClass)
-----------------
class MyUseClass
{
public slots:
void setMyClass(MySuperClass* superClass);
}
Q_DECLARE_METATYPE(MyUseClass)
Message 2 in thread
Hi
Some kind of silent on this mailing list ;) , but I thought just to tell my
workaround.
As it seems there is no possibility to make a QVariant automatically cast to a
different type (it would be a great feature for Qt 4.x to extend QMetaType
the way, that you can decide if autocasting is active or not when registering
a new usertype ).
Because of that every class the user can create in QScript through my
QSObjectFactories has a function to cast to its superclass like
"MySuperClass* castTo_MySuperClass() { return this; }".
That way the user can use an object of MyUseClass as an argument in a function
which requests a MySuperClass-object.
"var x = getBlaBla( objUseClass.castToMySuperClass() );"
I still would like to see QScript/QVariant doing the casting automatically,
because its not nice code using all this "castTo_..."-functions all over the
place in a script.
Greetings
Jens
Am Donnerstag, 6. Oktober 2005 00:52 schrieb Jens:
> Hi trolls
> This could be a feature-request for the next QSA ( but hopefully it is
> already possible with 1.2.0).
> After working with QSA for some time now I thought about the possibility of
> wrapping whole C++-libraries to be able to use them with QScripts. Together
> with the Qt-Plugin-System it would be possible to give an application new
> functions of external libraries by simply adding a new wrapper-plugin.
> I have already wrote a source-code-generator to be able to simply choose
> the include-files of the library to create wrapper-classes for each
> library-class. But now I´m really stuck.
>
> The problem is, that a slot like "void setMyClass(MySuperClass*)" cannot be
> used in a script with objects from classes which inherit MySuperClass.
> (which is possible in C++)
> With the class-definitions from the end of this email, I would like to run
> a script like this:
> var C = new MyClass();
> var useC = new MyUseClass();
> useC.setMyClass( C );
>
> What I did:
> I wrapped all classes of the external library and registerd these
> wrapper-classes in MyQSObjectFactory.
> The constructor of MyQSObjectFactory includes
> qRegisterMetaType<MySuperClass>("MySuperClass");
> qRegisterMetaType<MyClass>("MySuperClass");
> qRegisterMetaType<MyClass>("MyUseClass");
> ,too.
>
> The wrapper-classes are useable in QScripts as long as I call them with
> objects of desired class-Type.
> This would work:
> var superC = new MySuperClass();
> var useC = new MyUseClass();
> useC.setMyClass(superC);
> But this does not work:
> var C = new MySuperClass();
> var useC = new MyUseClass();
> useC.setMyClass(C);
>
> Qt´s metasystem should be able to figure out if the desired class is a
> superclass of the delivered one and could accept the variable.
> I wonder why QVariant does not cast automatically.
>
> What can I do ?
>
> Greetings
> Jens
>
> ======================================
> class MySuperClass
> {
> public slots:
> virtual void wrapSuperFunc1();
> virtual void wrapSuperFunc2();
> }
> Q_DECLARE_METATYPE(MySuperClass)
>
> class MyClass : public MySuperClass
> {
> public slots:
> void wrapFunc1();
> void wrapFunc2();
> }
> Q_DECLARE_METATYPE(MyClass)
> -----------------
>
> class MyUseClass
> {
> public slots:
> void setMyClass(MySuperClass* superClass);
> }
> Q_DECLARE_METATYPE(MyUseClass)
>
> To unsubscribe - send "unsubscribe" in the body to
> qsa-interest-request@xxxxxxxxxxxxx
Message 3 in thread
Jens wrote:
> Hi trolls
> This could be a feature-request for the next QSA ( but hopefully it is already
> possible with 1.2.0).
> After working with QSA for some time now I thought about the possibility of
> wrapping whole C++-libraries to be able to use them with QScripts. Together
> with the Qt-Plugin-System it would be possible to give an application new
> functions of external libraries by simply adding a new wrapper-plugin.
> I have already wrote a source-code-generator to be able to simply choose
> the include-files of the library to create wrapper-classes for each
> library-class. But now I´m really stuck.
>
> The problem is, that a slot like "void setMyClass(MySuperClass*)" cannot be
> used in a script with objects from classes which inherit MySuperClass.
> (which is possible in C++)
> With the class-definitions from the end of this email, I would like to run a
> script like this:
> var C = new MyClass();
> var useC = new MyUseClass();
> useC.setMyClass( C );
>
> What I did:
> I wrapped all classes of the external library and registerd these
> wrapper-classes in MyQSObjectFactory.
> The constructor of MyQSObjectFactory includes
> qRegisterMetaType<MySuperClass>("MySuperClass");
> qRegisterMetaType<MyClass>("MySuperClass");
> qRegisterMetaType<MyClass>("MyUseClass");
> ,too.
Hi Jens,
Granted that the types are QObjects and have the Q_OBJECT macro there
should be no problem in passing a subclass to a base class. The example
below works without problems. Its likely be that the registring of
metatypes introduces conflicts, because then there also exists a
QVariant conversion for the objects in addition to the QObject hiearachy.
Regards,
Gunnar
---
#include <qsinterpreter.h>
#include <qsobjectfactory.h>
#include <qapplication.h>
class BaseClass : public QObject { Q_OBJECT };
class SubClass : public BaseClass { Q_OBJECT };
class Object : public QObject
{
Q_OBJECT
public:
Object(QObject *parent = 0, const char *name = "context")
: QObject(parent)
{
setObjectName(name);
};
public slots:
void takeBaseClass(BaseClass *bc) {
printf("base class ok: %s\n", bc->metaObject()->className());
}
};
class Factory : public QSObjectFactory
{
public:
Factory()
{
registerClass("BaseClass", &BaseClass::staticMetaObject);
registerClass("SubClass", &SubClass::staticMetaObject);
}
QObject *create(const QString &name, const QVariantList &args,
QObject *context)
{
return name == "BaseClass" ? new BaseClass : new SubClass;
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QSInterpreter ip;
Object obj;
ip.addObjectFactory(new Factory);
ip.evaluate("var subclass = new SubClass();\n"
"context.takeBaseClass(subclass);\n"
"var baseclass = new BaseClass();\n"
"context.takeBaseClass(baseclass)\n", &obj);
}
#include "pass_baseclass.moc"
Message 4 in thread
Am Freitag, 7. Oktober 2005 13:28 schrieb Gunnar Sletta:
> Jens wrote:
> > Hi trolls
> > This could be a feature-request for the next QSA ( but hopefully it is
> > already possible with 1.2.0).
> > After working with QSA for some time now I thought about the possibility
> > of wrapping whole C++-libraries to be able to use them with QScripts.
> > Together with the Qt-Plugin-System it would be possible to give an
> > application new functions of external libraries by simply adding a new
> > wrapper-plugin. I have already wrote a source-code-generator to be able
> > to simply choose the include-files of the library to create
> > wrapper-classes for each library-class. But now I´m really stuck.
> >
> > The problem is, that a slot like "void setMyClass(MySuperClass*)" cannot
> > be used in a script with objects from classes which inherit MySuperClass.
> > (which is possible in C++)
> > With the class-definitions from the end of this email, I would like to
> > run a script like this:
> > var C = new MyClass();
> > var useC = new MyUseClass();
> > useC.setMyClass( C );
> >
> > What I did:
> > I wrapped all classes of the external library and registerd these
> > wrapper-classes in MyQSObjectFactory.
> > The constructor of MyQSObjectFactory includes
> > qRegisterMetaType<MySuperClass>("MySuperClass");
> > qRegisterMetaType<MyClass>("MySuperClass");
> > qRegisterMetaType<MyClass>("MyUseClass");
> > ,too.
>
> Hi Jens,
>
> Granted that the types are QObjects and have the Q_OBJECT macro there
> should be no problem in passing a subclass to a base class. The example
> below works without problems. Its likely be that the registring of
> metatypes introduces conflicts, because then there also exists a
> QVariant conversion for the objects in addition to the QObject hiearachy.
>
Hi Gunnar
I actually thought it´s a good idea to register all classes as metatypes, but
that introduces conflicts. After removing the QT_DECLARE_METATYPE lines I
have no problems with passing a subclass to a base class anymore.
Thanks for your help.
Greetings
Jens
> Regards,
> Gunnar
>
> ---
>
> #include <qsinterpreter.h>
> #include <qsobjectfactory.h>
>
> #include <qapplication.h>
>
> class BaseClass : public QObject { Q_OBJECT };
> class SubClass : public BaseClass { Q_OBJECT };
>
> class Object : public QObject
> {
> Q_OBJECT
> public:
> Object(QObject *parent = 0, const char *name = "context")
>
> : QObject(parent)
>
> {
> setObjectName(name);
> };
> public slots:
> void takeBaseClass(BaseClass *bc) {
> printf("base class ok: %s\n", bc->metaObject()->className());
> }
> };
>
> class Factory : public QSObjectFactory
> {
> public:
> Factory()
> {
> registerClass("BaseClass", &BaseClass::staticMetaObject);
> registerClass("SubClass", &SubClass::staticMetaObject);
> }
>
> QObject *create(const QString &name, const QVariantList &args,
> QObject *context)
> {
> return name == "BaseClass" ? new BaseClass : new SubClass;
> }
> };
>
> int main(int argc, char **argv)
> {
> QApplication app(argc, argv);
> QSInterpreter ip;
>
> Object obj;
>
> ip.addObjectFactory(new Factory);
>
> ip.evaluate("var subclass = new SubClass();\n"
> "context.takeBaseClass(subclass);\n"
> "var baseclass = new BaseClass();\n"
> "context.takeBaseClass(baseclass)\n", &obj);
> }
>
> #include "pass_baseclass.moc"
>
> To unsubscribe - send "unsubscribe" in the body to
> qsa-interest-request@xxxxxxxxxxxxx
Message 5 in thread
Hi
I have already mentioned this on this mailing list a week ago and could solve
my problems by removing the registration of the wrapper-class as a metatype.
But it seems that this solution only works with classes which have only one
single superclass. Right now my wrapper-class is defined like:
class myWrapper : public QObject, public QVSWrapper { ... }
( Because myWrapper is part of a plugin (I´m using the QPluginLoader) the
interface QVSWrapper must not inherit from QObject. .. But it has a function
"virtual QObject* object() { return m_pBaseObj; }" with m_pBaseObj gets set
in the constructor:
myWrapper::myWrapper(...) : QObject(), QVSWrapper(this) { ... }
)
If I have a slot which needs a QVSWrapper, it is not possible to give it a
myWrapper ... I get a segfault if I run a script like:
A)
var wrapper = new myWrapper();
Application.currentView.registerObject( wrapper );
Right now I have a slot "as_QVSObject()" like this:
QVSObject* as_QVSObject() { return this; }; to be able to write a script like:
B)
var wrapper = new myWrapper();
Application.currentView.registerObject( wrapper.as_QVSObject() );
The "normal" User will try to program a script like "A" and I would like to
make it work like this. What can I do?
Greetings
Jens
P.S:
I have seen that QMetaObject::superClass() returns only one single
QMetaObject. What happens if a class inherits from two superclasses?
Message 6 in thread
Hi
Here my result:
QObject can only be once in the "inheriting-chain". That´s one reason why my
QVSObject isn´t based on QObject. If my QVSObject isn´t based on QObject it
has no QMetaObject and isn´t known as a superclass to Qt :(
Anyway, QSA shouldn´t segfault if the user calls a function which expects a
QVSObject with a myWrapper.
( class myWrapper : public QObject, public QVSObject )
Greetings
Jens
Am Donnerstag, 13. Oktober 2005 13:31 schrieb Jens:
> Hi
> I have already mentioned this on this mailing list a week ago and could
> solve my problems by removing the registration of the wrapper-class as a
> metatype.
>
> But it seems that this solution only works with classes which have only one
> single superclass. Right now my wrapper-class is defined like:
> class myWrapper : public QObject, public QVSWrapper { ... }
>
> ( Because myWrapper is part of a plugin (I´m using the QPluginLoader) the
> interface QVSWrapper must not inherit from QObject. .. But it has a
> function "virtual QObject* object() { return m_pBaseObj; }" with m_pBaseObj
> gets set in the constructor:
> myWrapper::myWrapper(...) : QObject(), QVSWrapper(this) { ... }
> )
>
> If I have a slot which needs a QVSWrapper, it is not possible to give it a
> myWrapper ... I get a segfault if I run a script like:
> A)
> var wrapper = new myWrapper();
> Application.currentView.registerObject( wrapper );
>
> Right now I have a slot "as_QVSObject()" like this:
> QVSObject* as_QVSObject() { return this; }; to be able to write a script
> like: B)
> var wrapper = new myWrapper();
> Application.currentView.registerObject( wrapper.as_QVSObject() );
>
> The "normal" User will try to program a script like "A" and I would like to
> make it work like this. What can I do?
>
> Greetings
> Jens
>
> P.S:
> I have seen that QMetaObject::superClass() returns only one single
> QMetaObject. What happens if a class inherits from two superclasses?
>
> To unsubscribe - send "unsubscribe" in the body to
> qsa-interest-request@xxxxxxxxxxxxx