QCAD C++&Javascript混合调用

QCAD C++&Javascript混合调用

Javascript绑定C++类,与QML&JavascriptQt C++机制类似。

创建可供绑定的类

\\support\\examples\\exampleplugin2\\RExamplePlugin2.cpp

注意以下两点,绑定的前提。

  • Q_OBJECT
  • Q_DECLARE_METATYPE(MyClass*)
class MyClass : public QObject {
Q_OBJECT
public:
    MyClass() : QObject(), i(0), d(0.0) {}

    virtual int getInt() const {
        return i;
    }

    virtual double getDouble() const {
        return d;
    }

    virtual QString getString() const {
        return s;
    }

    virtual void setInt(int v) {
        i = v;
    }

    virtual void setDouble(int v) {
        d = v;
    }

    virtual void setString(const QString& v) {
        s = v;
    }

    void emitSignal() {
        emit mySignal(i);
    }

signals:
    void mySignal(int code);

private:
    int i;
    double d;
    QString s;
};

Q_DECLARE_METATYPE(MyClass*)

创建脚本类

/**
 * Script binding for MyClass.
 */
class EcmaMyClass {
public:
    static void initEcma(QScriptEngine& engine);

    static QScriptValue createMyClass(QScriptContext* context, QScriptEngine* engine);
    static QScriptValue myClassToString(QScriptContext *context, QScriptEngine *engine);
    static MyClass* getSelfMyClass(const QString& fName, QScriptContext* context);

    static QScriptValue getInt(QScriptContext* context, QScriptEngine* engine);
    static QScriptValue getDouble(QScriptContext* context, QScriptEngine* engine);
    static QScriptValue getString(QScriptContext* context, QScriptEngine* engine);

    static QScriptValue setInt(QScriptContext* context, QScriptEngine* engine);
    static QScriptValue setDouble(QScriptContext* context, QScriptEngine* engine);
    static QScriptValue setString(QScriptContext* context, QScriptEngine* engine);

    static QScriptValue emitSignal(QScriptContext* context, QScriptEngine* engine);
};
void EcmaMyClass::initEcma(QScriptEngine& engine) {
    QScriptValue* proto = new QScriptValue(engine.newVariant(qVariantFromValue((MyClass*)0)));

    // base class:
    QScriptValue dpt = engine.defaultPrototype(qMetaTypeId<QObject*>());
    proto->setPrototype(dpt);

    REcmaHelper::registerFunction(&engine, proto, myClassToString, "toString");

    engine.setDefaultPrototype(qMetaTypeId<MyClass*>(), *proto);
                        
    QScriptValue ctor = engine.newFunction(createMyClass, *proto, 0);
    engine.globalObject().setProperty("MyClass", ctor, QScriptValue::SkipInEnumeration);

    // register function getInt:
    REcmaHelper::registerFunction(
        &engine, 
        proto,            // prototype
        getInt,           // reference to static function
        "getInt");        // name in ECMAScript

    REcmaHelper::registerFunction(&engine, proto, getDouble, "getDouble");
    REcmaHelper::registerFunction(&engine, proto, getString, "getString");

    REcmaHelper::registerFunction(&engine, proto, setInt,    "setInt");
    REcmaHelper::registerFunction(&engine, proto, setDouble, "setDouble");
    REcmaHelper::registerFunction(&engine, proto, setString, "setString");

    REcmaHelper::registerFunction(&engine, proto, emitSignal, "emitSignal");
}

/**
 * Constructor for MyClass.
 * Allows instantiation in ECMAScript as:
 * 
 * var v = new MyClass();
 */
QScriptValue EcmaMyClass::createMyClass(QScriptContext* context, QScriptEngine* engine) {
    if (context->thisObject().strictlyEquals(engine->globalObject())) {
        return REcmaHelper::throwError(QString::fromLatin1("MyClass(): Did you forget to construct with 'new'?"), context);
    }
    
    // constructor without arguments:
    if(context->argumentCount() == 0) {
        MyClass* cppResult = new MyClass();
        return engine->newQObject(context->thisObject(), cppResult);
    }
    else {
        return REcmaHelper::throwError(QString::fromLatin1("MyClass(): no matching constructor found."), context);
    }
}

/**
 * Allows implicit converstion of MyClass objects to strings:
 *
 * var v = new MyClass();
 * qDebug(v);
 * // MyClass(0x12345678)
 */
QScriptValue EcmaMyClass::myClassToString(QScriptContext *context, QScriptEngine *engine) {
    Q_UNUSED(engine)

    MyClass* self = getSelfMyClass("toString", context);
    if (self!=NULL) {
        return QScriptValue(QString("MyClass(0x%1)").arg((unsigned long int)self, 0, 16));
    }
    return QScriptValue();
}

/**
 * \\return MyClass object from given script context. Helper function.
 */
MyClass* EcmaMyClass::getSelfMyClass(const QString& fName, QScriptContext* context) {
    MyClass* self = REcmaHelper::scriptValueTo<MyClass >(context->thisObject());
    if (self == NULL){
        if (fName!="toString") {
            REcmaHelper::throwError(QString("MyClass.%1(): This object is not a MyClass").arg(fName), context);
        }
        return NULL;
    }
    
    return self;
}

/**
 * Binding for getInt.
 */
QScriptValue EcmaMyClass::getInt(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("getInt", context);
    if (self!=NULL) {
        int i = self->getInt();
        return QScriptValue(engine, i);
    }
    return QScriptValue();
}

/**
 * Binding for getDouble.
 */
QScriptValue EcmaMyClass::getDouble(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("getDouble", context);
    if (self!=NULL) {
        double d = self->getDouble();
        return QScriptValue(engine, d);
    }
    return QScriptValue();
}

/**
 * Binding for getString.
 */
QScriptValue EcmaMyClass::getString(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("getString", context);
    if (self!=NULL) {
        QString s = self->getString();
        return QScriptValue(engine, s);
    }
    return QScriptValue();
}

/**
 * Binding for setInt.
 */
QScriptValue EcmaMyClass::setInt(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("setInt", context);
    if (self!=NULL) {
        if (context->argumentCount()==1 && context->argument(0).isNumber()) {
            int a0 = (int)context->argument(0).toNumber();
            self->setInt(a0);
        } 
        else {
            return REcmaHelper::throwError("Wrong number/types of arguments for EcmaMyClass.setInt().", context);
        }
    }
    return QScriptValue();
}

/**
 * Binding for setDouble.
 */
QScriptValue EcmaMyClass::setDouble(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("setDouble", context);
    if (self!=NULL) {
        if (context->argumentCount()==1 && context->argument(0).isNumber()) {
            double a0 = (double)context->argument(0).toNumber();
            self->setDouble(a0);
        } 
        else {
            return REcmaHelper::throwError("Wrong number/types of arguments for EcmaMyClass.setDouble().", context);
        }
    }
    return QScriptValue();
}

/**
 * Binding for setString.
 */
QScriptValue EcmaMyClass::setString(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("setString", context);
    if (self!=NULL) {
        if (context->argumentCount()==1 && context->argument(0).isString()) {
            QString a0 = context->argument(0).toString();
            self->setString(a0);
        } 
        else {
            return REcmaHelper::throwError("Wrong number/types of arguments for EcmaMyClass.setString().", context);
        }
    }
    return QScriptValue();
}

/**
 * Binding for emitSignal.
 */
QScriptValue EcmaMyClass::emitSignal(QScriptContext* context, QScriptEngine* engine) {
    MyClass* self = getSelfMyClass("emitSignal", context);
    if (self!=NULL) {
        if (context->argumentCount()==0) {
            self->emitSignal();
        }
        else {
            return REcmaHelper::throwError("Wrong number/types of arguments for EcmaMyClass.emitSignal().", context);
        }
    }
    return QScriptValue();
}

QCAD 中的脚本绑定类

QCAD为底层的C++类生成了可供脚本调用的脚本绑定类。

\\src\\scripting\\ecmaapi\\generated

原文链接:https://blog.csdn.net/mrbaolong/article/details/111885974

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容