Проблема
Я делаю проект, используя Q_OBJECT и Q_PROPERTY для доступа к некоторым объектам из скриптов. У меня две проблемы:
- создание классов, использующих предварительные объявления, доступными для сценариев
- возвращение свойства в виде указателя
Пояснения
1. Зачем направлять декларацию?
Класс B получает предварительное объявление для A, потому что A нуждается в полном типе B в заголовке из-за шаблонов. B требуется только неполный тип (A*) в заголовке, поэтому предварительное объявление допустимо.
2. Зачем возвращать указатель?
Мы не можем вернуть копию, так как нам нужен доступ к реальному объекту в скрипте. Мы не можем вернуть ссылку, так как Qt не позволяет слотам возвращать ссылки — их тип будет проигнорирован, они будут возвращать только void*.
Код
Полная загрузка кода в pastebin или в виде ZIP-архива, или в виде ZIP-архива минимального примера доступен для тестирования/воспроизведения: мне нужно было разделить файлы для форвардной декларации и для MOC. Я добавил Makefile для проверки. Сделать отладки: g++, moc, Qt.
Важные части
class A; // forward declaration necessary, see explanation above
class B : public QObject {
Q_OBJECT
Q_PROPERTY(A a READ GetA) // <-- ERROR HERE
// ...
public slots:
A* GetA() {
return mA;
}
private:
A* mA;
// ...
}
Строка ошибки в скрипте:
print(bObj.GetA().GetName());
Ошибка компиляции
Эта ошибка исчезает, когда я комментирую Q_PROPERTY выше.
tmp/B.moc.hpp:95:51: error: invalid use of incomplete type ‘struct A’
tmp/../B.hpp:10:7: error: forward declaration of ‘struct A’
Исключение скрипта
Если исключить Q_PROPERTY и вызвать метод GetA() в качестве слота из скрипта, я получаю следующее исключение:
Line 7: "TypeError: cannot call GetA(): unknown return type `A*'
(register the type with qScriptRegisterMetaType())"
При регистрации A* с qRegisterMetaType<A*>("A*");
это меняется на:
Line 7: "TypeError: Result of expression 'bObj.GetA().GetName'
[undefined] is not a function."
Это показывает, что GetA() не возвращает объект A или каким-то образом возвращает указатель, но скрипт не может его разыменовать. GetA() фактически возвращает QVariant(A*)
, можно ли это как-то использовать?
Вопросы:
- Можно ли как-то сделать Q_PROPERTY из неполного типа или как избежать форвардного объявления?
- Могу ли я вернуть ссылку в слоте (может быть, какие-то хитрости, например, класс, который оборачивает указатель и переопределяет скрипт
operator.
, если существует что-то подобное) или - Могу ли я как-то разыменовать QVariant(A*) в A в QtScript?