You are doing it wrong. You should be registering default prototypes for your types (i.e. Drawable* and MeshDrawable*) and not your prototypes. Then you should be exposing instances of your types and not the prototypes. Furthermore you'll have problems while casting objects containing virtual methods.
#include <QCoreApplication>
#include <QScriptEngine>
#include <QScriptable>
#include <QPoint>
class Drawable {
public:
int x() const { return pt.x(); }
int y() const { return pt.y(); }
void setX(int xx) { pt.setX(xx); }
void setY(int yy) { pt.setY(yy); }
private:
};
class MeshDrawable : public Drawable {
public:
};
class DrawablePrototype
: public QObject,
public QScriptable
{ Q_OBJECT
public:
public slots:
void setX(int x) {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
drawable->setX(x);
}
void setY(int y) {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
drawable->setY(y);
}
public:
Q_INVOKABLE virtual int x() const {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
return drawable->x();
}
Q_INVOKABLE virtual int y() const {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
return drawable->y();
}
private:
};
class MeshDrawablePrototype
: public QObject,
public QScriptable
{ Q_OBJECT
public:
public:
Q_INVOKABLE virtual int x() const {
MeshDrawable *drawable = qscriptvalue_cast<MeshDrawable*>(thisObject());
return -drawable->x();
}
Q_INVOKABLE virtual int y() const {
MeshDrawable *drawable = qscriptvalue_cast<MeshDrawable*>(thisObject());
return -drawable->y();
}
};
//QScriptValue constructDrawable(QScriptContext *context, QScriptEngine *engine) {
// if (!context->isCalledAsConstructor())
// return context->throwError(QScriptContext::SyntaxError, "please use the 'new' operator");
// return engine->newVariant(context->thisObject(), qVariantFromValue(new Drawable));
//}
Q_DECLARE_METATYPE(Drawable*)
Q_DECLARE_METATYPE(MeshDrawable*)
#include "main.moc"
#include <QtDebug>
int main(int argc, char *argv[])
{
QScriptEngine engine;
DrawablePrototype drawableProto;
MeshDrawablePrototype meshProto;
QScriptValue dPValue = engine.newQObject(&drawableProto);
QScriptValue mPValue = engine.newQObject(&meshProto);
engine.setDefaultPrototype(qMetaTypeId<Drawable*>(), dPValue);
engine.setDefaultPrototype(qMetaTypeId<MeshDrawable*>(), mPValue);
mPValue.setPrototype(dPValue);
Drawable *drawable = new Drawable;
MeshDrawable *meshDrawable = new MeshDrawable;
QScriptValue drawableObj = engine.newVariant(qVariantFromValue<Drawable*>(drawable));
QScriptValue meshDrawableObj = engine.newVariant(qVariantFromValue<MeshDrawable*>(meshDrawable));
engine.globalObject().setProperty("drawable", drawableObj);
engine.globalObject().setProperty("meshDrawable", meshDrawableObj);
qDebug() << engine.evaluate("drawable.setX(7); drawable.x()").toString();
//qDebug() << engine.evaluate("meshDrawable.setX(7); meshDrawable.x()").toString();
delete drawable;
delete meshDrawable;
}
#include <QCoreApplication>
#include <QScriptEngine>
#include <QScriptable>
#include <QPoint>
class Drawable {
public:
int x() const { return pt.x(); }
int y() const { return pt.y(); }
void setX(int xx) { pt.setX(xx); }
void setY(int yy) { pt.setY(yy); }
private:
QPoint pt;
};
class MeshDrawable : public Drawable {
public:
};
class DrawablePrototype : public QObject, public QScriptable {
Q_OBJECT
public:
DrawablePrototype(QObject *parent = 0) : QObject(parent) {}
public slots:
void setX(int x) {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
drawable->setX(x);
}
void setY(int y) {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
drawable->setY(y);
}
public:
Q_INVOKABLE virtual int x() const {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
return drawable->x();
}
Q_INVOKABLE virtual int y() const {
Drawable *drawable = qscriptvalue_cast<Drawable*>(thisObject());
return drawable->y();
}
private:
};
class MeshDrawablePrototype : public QObject, public QScriptable {
Q_OBJECT
public:
MeshDrawablePrototype(QObject *parent = 0) : QObject(parent) {}
public:
Q_INVOKABLE virtual int x() const {
MeshDrawable *drawable = qscriptvalue_cast<MeshDrawable*>(thisObject());
return -drawable->x();
}
Q_INVOKABLE virtual int y() const {
MeshDrawable *drawable = qscriptvalue_cast<MeshDrawable*>(thisObject());
return -drawable->y();
}
};
//QScriptValue constructDrawable(QScriptContext *context, QScriptEngine *engine) {
// if (!context->isCalledAsConstructor())
// return context->throwError(QScriptContext::SyntaxError, "please use the 'new' operator");
// return engine->newVariant(context->thisObject(), qVariantFromValue(new Drawable));
//}
Q_DECLARE_METATYPE(Drawable*)
Q_DECLARE_METATYPE(MeshDrawable*)
#include "main.moc"
#include <QtDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QScriptEngine engine;
DrawablePrototype drawableProto;
MeshDrawablePrototype meshProto;
QScriptValue dPValue = engine.newQObject(&drawableProto);
QScriptValue mPValue = engine.newQObject(&meshProto);
engine.setDefaultPrototype(qMetaTypeId<Drawable*>(), dPValue);
engine.setDefaultPrototype(qMetaTypeId<MeshDrawable*>(), mPValue);
mPValue.setPrototype(dPValue);
Drawable *drawable = new Drawable;
MeshDrawable *meshDrawable = new MeshDrawable;
QScriptValue drawableObj = engine.newVariant(qVariantFromValue<Drawable*>(drawable));
QScriptValue meshDrawableObj = engine.newVariant(qVariantFromValue<MeshDrawable*>(meshDrawable));
engine.globalObject().setProperty("drawable", drawableObj);
engine.globalObject().setProperty("meshDrawable", meshDrawableObj);
qDebug() << engine.evaluate("drawable.setX(7); drawable.x()").toString();
//qDebug() << engine.evaluate("meshDrawable.setX(7); meshDrawable.x()").toString();
delete drawable;
delete meshDrawable;
}
To copy to clipboard, switch view to plain text mode
Uncommenting the second qDebug() line crashes the app, probably because the cast in setX() malforms the object.
Anyway, if the only thing you want is to indeed have wrappers for your classes then you can do so:
class Drawable_Wrapper
: public QObject { Q_OBJECT
public:
Drawable_Wrapper
(Drawable
*drawable,
QObject *parent
= 0) : QObject(parent
) { m_drawable
= drawable;
}public slots:
virtual void setX(int x) { m_drawable->setX(x); }
private:
Drawable *m_drawable;
};
class MeshDrawable_Wrapper : public Drawable_Wrapper {
Q_OBJECT
public:
MeshDrawable_Wrapper
(MeshDrawable
*meshDrawable,
QObject *parent
= 0) : Drawable_Wrapper
(meshDrawable, parent
) {}public slots:
virtual void setX(int x) { Drawable_Wrapper::setX(-x); }
};
Drawable_Wrapper wrapper(new Drawable);
MeshDrawable_Wrapper wrapper2(new MeshDrawable);
engine.globalObject()->setProperty("drawable", engine.newQObject(&wrapper));
engine.globalObject()->setProperty("meshDrawable", engine.newQObject(&wrapper2));
class Drawable_Wrapper : public QObject {
Q_OBJECT
public:
Drawable_Wrapper(Drawable *drawable, QObject *parent = 0) : QObject(parent) { m_drawable = drawable; }
public slots:
virtual void setX(int x) { m_drawable->setX(x); }
private:
Drawable *m_drawable;
};
class MeshDrawable_Wrapper : public Drawable_Wrapper {
Q_OBJECT
public:
MeshDrawable_Wrapper(MeshDrawable *meshDrawable, QObject *parent = 0) : Drawable_Wrapper(meshDrawable, parent) {}
public slots:
virtual void setX(int x) { Drawable_Wrapper::setX(-x); }
};
Drawable_Wrapper wrapper(new Drawable);
MeshDrawable_Wrapper wrapper2(new MeshDrawable);
engine.globalObject()->setProperty("drawable", engine.newQObject(&wrapper));
engine.globalObject()->setProperty("meshDrawable", engine.newQObject(&wrapper2));
To copy to clipboard, switch view to plain text mode
Then you have inheritance on C++ side instead of using prototypes. Not exactly the same functionality though.
Bookmarks