Можем ли мы генерировать абстрактные классы адаптера Qt D-Bus?
Я использую qdbusxml2cpp
инструмент для создания класса адаптера D-Bus для моего сервера D-Bus. Тем не менее, он имеет следующие недостатки:
Код генерируется один раз, и тогда вы не должны его изменять. Но что, если мы должны внести изменения (см. Ниже), а затем изменения XML (конечно, обратно совместимым способом)?
Предполагается, что "Adaptee" имеет те же функции и подписи, что и интерфейс D-Bus. В моем случае это не совсем так, например, некоторые методы имеют разные имена. Поскольку сгенерированный код использует
QMetaObject::invokeMethod
, это обнаруживается только во время выполнения. И мы не можем разумно модифицировать сгенерированный код, если нам может понадобиться восстановить его в будущем.
Было бы намного лучше, на мой взгляд, если бы qdbusxml2cpp
будет генерировать абстрактный класс, просто заголовок, где все методы являются чисто виртуальными. Затем я могу написать реализацию этого класса, которая просто вызывает нужные методы для адаптера, не проходя через систему метатипов Qt. Это решает обе проблемы:
Если XML изменяется, мы просто восстанавливаем заголовок. Теперь компилятор будет жаловаться, пока мы не реализуем новый интерфейс правильно.
У нас есть свобода вызывать любые функции, которые нам нравятся, в классе "adaptee" вместо того, чтобы поддерживать ту же самую сигнатуру, что и в общедоступном интерфейсе D-Bus.
Я не мог найти инструмент или qdbusxml2cpp
вилка, которая делает вышеперечисленное. Прежде чем написать сам, есть ли проблемы с вышеупомянутым подходом, которые я мог бы пропустить, по дизайну или по техническим причинам? Возможно, ограничения системы метатипов связаны с абстрактными классами или чисто виртуальными функциями?
Обратите внимание, что это необходимо для работы не только с методами, но и со свойствами и сигналами.
Я также подумал о написании "промежуточного" адаптера, который обертывает "adaptee" и предлагает точный интерфейс, которого ожидает адаптер D-Bus, но адаптер D-Bus все равно будет использовать систему метатипов и проверки во время выполнения. Конечно, мы можем сделать лучше.
1 ответ
Как вы обнаружили, нет способа делать то, что вы хотите с qdbusxml2cpp
непосредственно. Это означает, что у нас есть несколько вариантов, некоторые из которых вы уже перечислили:
Было бы намного лучше, на мой взгляд, если бы
qdbusxml2cpp
будет генерировать абстрактный класс, просто заголовок, где все методы являются чисто виртуальными.
Похоже, в этом нет ничего страшного, хотя некоторые инструменты /IDE могут не очень хорошо с этим работать. Недостатком этого является то, что всякий раз, когда что-то меняется, вам нужно будет также обновить все части исходного кода C++, а не только заголовок, например, если есть шаблон, который должен меняться при добавлении нового метода.
Код генерируется один раз, и тогда вы не должны его изменять. Но что, если мы должны внести изменения (см. Ниже), а затем изменения XML (конечно, обратно совместимым способом)?
В зависимости от того, насколько хорошо работает генератор кода, мне иногда было проще просто использовать сгенерированный код в качестве отправной точки, а затем просто изменить его оттуда. Большинство шейгов, как правило, довольно простые.
Еще один вариант, который вы можете сделать, это использовать другую библиотеку для связи с DBus.
Я использую (и поддерживаю) dbus-cxx; есть включенный инструмент (dbus-cxx-xml2cpp), который генерирует адаптируемые классы, похожие на выходные данные qdbusxml2cpp
в этом классе Adaptee просто вызывает другой класс, который обрабатывает фактический ответ. Недостатком является то, что инструмент xml2cpp не настолько умен, и не всегда будет выводить правильный код. И чтобы использовать dbus-cxx в приложении Qt, вам нужно отключить ключевые слова Qt. Тем не менее, он имеет преимущество использования шаблонных функций, поэтому, если ваша подпись неверна, вы получите ошибку компиляции.
К сожалению, на самом деле не существует хорошего "правильного" способа сделать это, поэтому я боюсь, что у меня нет ответа "Сделай так".