QtScript плюс перечисления

Я добавляю QScript в свое приложение Qt. Я уже добавил метаданные и использую некоторые функции метаданных для опроса кода C++. Это прекрасно работает - я могу перемещаться по иерархии объектов и выводить значения (включая перечисления).

Но я не вижу, чтобы перечисления работали в скрипте Qt.

У меня есть свой класс...

class HalPin : public QObject
{
Q_OBJECT
public:
enum EHalPinType
{
    Bit = HAL_BIT,
    Float = HAL_FLOAT,
    S32 = HAL_S32,
    U32 = HAL_U32
};

enum EHalPinDirection
{
    In = HAL_IN,
    Out = HAL_OUT,
    IO = HAL_IO
};
Q_ENUMS(EHalPinType)
Q_ENUMS(EHalPinDirection)

public:
explicit HalPin(QObject *parent = 0);

signals:

public slots:

};

Q_DECLARE_METATYPE(HalPin::EHalPinType)
Q_DECLARE_METATYPE(HalPin::EHalPinDirection)
Q_DECLARE_METATYPE(HalPin*)

У меня есть другой класс, который имеет метод, который принимает перечисления в качестве аргументов...

class EmcHal : public QObject
{
Q_OBJECT
public:
explicit EmcHal(QString moduleName, QObject *parent = 0);

signals:

public slots:
QObject *createHalPin( HalPin::EHalPinType, HalPin::EHalPinDirection, QString name );
};

Этот класс представлен в другом классе - извините, я должен был упростить пример. Если я напишу следующий код jscript,

var nextPagePin1 = Emc.hal.createHalPin();

Я получаю сообщение об ошибке...

SyntaxError: too few arguments in call to createHalPin(); candidates are createHalPin(HalPin::EHalPinType,HalPin::EHalPinDirection,QString)

Итак, похоже, что типы перечислений известны qtscript.

Что я пытаюсь сделать, это установить аргументы enum из jscript. Я перепробовал много комбинаций...

Bit
EHalPinType.Bit
HalPin.EHalPinType.Bit

и многое другое.

Если я пытаюсь использовать целые числа, я получаю...

TypeError: cannot call createHalPin(): argument 1 has unknown type `HalPin::EHalPinType' (register the type with qScriptRegisterMetaType())

что подразумевает, что jscript не знает о моих перечислениях.

Какие-либо предложения?

Нужно ли использовать qRegisterMetaType или qScriptRegisterMetaType для доступа к моим перечислениям? Документация не предполагает, что мне нужно это сделать. Нужно ли реализовывать функции конвертера для метода qScriptRegisterMetaType.

Или мой синтаксис просто неправильно для jscript?

У кого-нибудь есть рабочий пример?

Спасибо фрэнк

2 ответа

Чтобы ответить на мой собственный вопрос...

Ну, не столько ответ на вопрос, а пример "это работает"...

Как я упоминал выше, я не смог заставить работать перечисления в метаданных и jscript одновременно с использованием макросов qt. Несмотря на то, что перечисление появилось в qscript (я проверил в браузере отладчика скриптов), оно не получило правильное целое число.

Мне пришлось добавить QMetaObject для перечисления. Это дало мне элементы enum и правильные целочисленные значения.

Но это все равно дало мне неизвестную ошибку типа, поэтому мне нужно было использовать qScriptRegisterMetaType() для регистрации функций преобразования для типов.

Это класс, который я использую для 1 перечисления. Это настолько минимально, насколько я могу это сделать. Я должен быть в состоянии использовать макросы, чтобы уменьшить его немного больше, но есть ограничения на то, что можно макросизировать, из-за требований qt moc.

#include <QObject>
#include <QMetaType>
#include <QScriptEngine>

#include "hal.h"


class CEHalPinType : public QObject
{
Q_OBJECT
public:
    explicit CEHalPinType(QObject *parent = 0) : QObject(parent) {}
    explicit CEHalPinType(const CEHalPinType &other) : QObject(other.parent()) {}
    virtual ~CEHalPinType() {}

    enum EHalPinType
    {
        Bit = HAL_BIT,
        Float = HAL_FLOAT,
        S32 = HAL_S32,
        U32 = HAL_U32
    };
    Q_ENUMS( EHalPinType )

private:
    static QScriptValue toScriptValue(QScriptEngine *engine, const EHalPinType &s)
    {
        return engine->newVariant((int)s);
    }

    static void fromScriptValue(const QScriptValue &obj, EHalPinType &s)
    {
        s = (EHalPinType)obj.toInt32();
    }
    static QScriptValue qscriptConstructor( QScriptContext *context, QScriptEngine *engine )
    {
        return engine->newQObject( new CEHalPinType(context->argument(0).toQObject()), QScriptEngine::ScriptOwnership);
    }
public:
    static void Init( const char *name, QScriptEngine *engine )
    {
        qScriptRegisterMetaType(engine, toScriptValue, fromScriptValue);
        QScriptValue metaObject = engine->newQMetaObject( &staticMetaObject, engine->newFunction(qscriptConstructor) );
        engine->globalObject().setProperty( name, metaObject );
    }
};

Q_DECLARE_METATYPE(CEHalPinType::EHalPinType)

И мой jscript выглядит так...

var nextPagePin = Emc.hal.createHalPin(EHalPinType.Bit,EHalPinDirection.In,"nexis.NextPage");

К сожалению. Я бросил пистолет на этом. Хотя сценарии работали, я отказался от возможности преобразовывать перечисления в строки с использованием данных qmetaobject.

И, кажется, нет автоматического способа сделать это.

Проблема в том, что я переместил перечисления из класса, где были определены свойства, которые использовали перечисления. Хотя Q_ENUMS и Q_PROPERTY компилируются, если я использую QMetaProperty для чтения перечисления, это не работает. Возвращаемый QVariant показывает правильный тип данных "CEHalPinType::EHalPinType", но он не проходит тест isEnum(), а canConvert(QVariant::String) тоже не выполняется. Это связано с тем, что когда код qmetaobject отправляется на поиск типа enum, он ищет только текущий класс и его производные классы. Он не ищет другие классы. Вот почему это сработало, когда enum был членом класса, который также имел свойства.

Моя работа вокруг, как предлагалось в другом месте, состояла в том, чтобы создать мой собственный QMap известных перечислений, сохраняя имя строки в отображении qmetaobject. Я использовал шаблонный базовый класс и использовал T::staticMetaObject, чтобы получить мета-объект.

Другие вопросы по тегам