Как стать автором
Обновить

Комментарии 14

А pimpl не проще в этом случае?
Что именно по вашему можно было бы вынести в приватную имплементацию? На мой взгляд реализации стратегий — возможно. Других мыслей не приходит. В плане архитекруты класс далек от идеала и его можно реструктурировать и расширять на свой «вкус». В этой стать сделан основной упор на автоматические контроль жизни объектов, расшаренных в QML-C++.
Статья однозначно полезная и интересная
Я бы вынес в закрытую имплементацию весь класс, а во внешний бы засадил умный указатель, тогда умный указатель становится доступен и внутри GC JS и он уже обеспечивает нам корректное освобождение при разрушении последнего объекта.
Я думал о идее, чтоб сам умный указатель представлял тот объект, который мы хотим экспортировать, однако столкнулся с подводными камнями, когда объест на стороне C++ сам себя разрушает. Не могли бы вы написать пример(хотя бы псевдокод)? Возможно я что-то упустил…
class ApproxPrivate {
//....
};

class Approx: public QObject {
  Q_OBJECT
// ...  
  Approx() {
  // ...
  QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); // нормально ли что QML знает обо всех объектах? Нет ли способа передать владение только при передаче внутрь QML ?
  }
  
private:
  QSharedPointer<ApproxPrivate> d_ptr;
  // По идее должно работать Q_DECLARE_PRIVATE(Approx)
  // И если работает тогда доступно Q_D(Approx)
};


Я не проверял эту идею, но скорее всего сработает.
Вообще у меня не праздный интерес, может быть у вас уже есть тесты на которых можно проверять утечки и сегфолты?
И отдавать в QML указатель класса Approx? Но тода при выходе из области видимости объект класса Approx разрушится, разрушив d_ptr и QML в дальнейшем будет иметь доступ к уже невалидному объекту.
Так если мы в QML отдаём владение, то Approx должен быть на куче в любом случае, с чего ему разрушаться то?
В случае если мы его создадим в куче и передадим в QML во владение, то Qml разрушит обеъкт, когда его ссылки закончатся. После этого C++ обратится уже к разрушенному объекту.
Всё так, потому что мы отдаём владение в QML и с этим конкретным экземпляром больше не должны работать, а если хотим — делаем копию, копии такого объекта очень дешёвые
Approx *toQML = new Approx();
Approx toC = *toQML;  // а можно и в кучу если надо
Я так понял, Вы имеете в виду, что Approx будет оберткой над общим объектом и будет делигировать вызовы функций/свойств/слотов/сигналов этому объекту. Это можно было бы реализовать с помощью переопределения функции QMetaObject::qt_metaCall(). Этот похдход имеет место, но в нем есть два недостатка:

1.Фунции, которые экспортируют объект в QML, должны иметь возвращаемый тип QObject*, а не тот тип, который реально хотим экспортировать
Например, уже не получиться реализовать функцию подобным образом:
Q_INVOKABLE SomeObject* createObject(QString const& name, int value) {
 Approx *toQML = new Approx();
 return toQML;
}

только так:
Q_INVOKABLE QObject* createObject(QString const& name, int value) {
 Approx *toQML = new Approx();
 return toQML;
}

Если реализовывать такой подход, теряется типобезопасность, ведь подобные функции могут вызываться так же из C++ кода.

2. второй недостаток не столь существенный, однако он есть: Qt Creator не сможет авктопомплитить свойства, методы этого объекта в QML коде.

А пользоваться-то как?
Я как-то недавно с подобной проблемой сталкивался, поэтому можете считать меня эталонным представителем целевой аудитории. И пока не особо понятно, как следует применять и насколько будет удобно.
Спасибо, за ценное замечание по поводу использования. В ближайшее время допишу пример использования.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории