Haftalık C++ 25 – QML/C++ Entegrasyonu

Sizlerin de takip ettiği üzere, bir süredir  QT ve QML kullanımına ilişkin bir çok yazı ve kod paylaşıyorum. Bugün de sizlerle QML ile C++’ı nasıl kullanabileceğinize, bu kullanım sırasında dikkat etmeniz gereken hususlara, bir kaç örnek üzerinden bakacağız. Bu yazı ile birlikte, kendi QML ve C++ uygulamarınızı kolay bir şekilde geliştirebileceğinizi umuyorum.

Bu yazıda, QML ve C++ kullanımına ilişkin, temel ve gerekli olduğunu düşündüğüm bir takım konulara değineceğim, daha karmaşık konulara (C++ modelleri ile QML’i nasıl entegre edebiliriz, özellikle ListView, ComboBox gibi bileşenler için) ise farklı yazılarda eğileceğiz.

Bu yazıma belli başlı sorular ile yön vermek istiyorum. O zaman ilk soru ile başlayalım.

Neden C++/QML kullanmalıyım?

Aslında bakarsanız bu soru, biraz da sizin ihtiyaçlarınıza bağlı. Normal şartlarda, sadece QML veya sadece C++ kullanarak da pekala bir çok ihtiyacınızı gerçekleştirebilecek uygulamalar geliştirebilirsiniz. Bana kalırsa bu birlikteliğin, en önemli iki avantajı, görsel kısımlar ile işlem yoğun kısımları birbirinden kolay bir şekilde ayırmak ve hali hazırda mevcut kodlarınızı kullanabilmek derim. Tabi, C++ kullanabilmek de, benim gibi yazılımperver dostlar için bir motivasyon olabilir. Bu hususları biraz daha anlamak adına C++ mı QML mi sorularına, ayrı ayrı bakalım.

Neden C++ kullanmalıyız?

Eğer uzun bir süredir sayfamı takip ediyorsanız artık C++’ı neden ve nerede kullanmanız gerektiğini biliyorsunuzdur diye umuyorum ama burada QML ve QT anlamında tekrar bakacak ve hatırlayacak olursak. Eğer veri yoğun ve performans kritik bir iş yapacaksanız. C++ sizin için doğru seçim olacaktır. QML ile karşılaştıracak olursak, C++ kodu, binary dosyalar oluşturacak ve QML ve benzeri kodlara göre daha tutarlı ve emniyetli bir seçenek olacaktır. Her ne kadar ben henüz bu özellikleri kullanmamış olsam da, QT C++ kütüphaneleri bazı ileri seviye kullanımlarda QML’den daha fazla özellik sunuyorlarmış.

Son olarak, QML, açılış zamanında bir takım hazırlıklar ve işler yaptığı için C++ uygulamasına göre biraz daha yavaş olacaktır. Bu konu ile ilgili aşağıdaki sayfada güzel bir karşılaştırma ve analiz bulabilirsiniz. Şunu da ifade etmeliyim ki, ilgili yazı Qt 5.8 için yazılmış, yani o zamandan bu yana performans anlamında ilerleme olduğunu muhakkak göz önünde bulundurmalısınız.

https://woboq.com/blog/qml-vs-cpp-for-application-startup-time.html

Şimdi, diğer soruya bakalım.

Neden QML kullanmalıyız?

Özellikle, çoklu platform destekleyecek arayüzlerin geliştirilmesi için QML kullanılmasını tavsiye ediyoruz. Aslında bu konuya aşağıdaki yazımda kısaca değinmiştim:

QT (BÇOM Serisi – 2)

Burada bir kaç önemli hususun üzerinden geçeceğiz. Öncelikle QML ve Javascript hem öğrenmesi kolay hem de arayüz geliştirmek, bu sayede hem zamandan hem geliştirilecek kod miktarı ciddi anlamda azalmakta. QML ile gelen özelliklerin bağlanması, durum yönetimleri, sinyaller gibi bir çok mekanizma da size bu anlamdan kolaylık sağlayacaklar. Bir diğer önemli avantaj da, animasyonların çok kolay bir şekilde yapılabilmesi ve bunların mevcut bileşenler ile kolay bir şekilde ilişkilendirilebilmesi. Görselleştirme performans anlamında da QML’in avantajı mevcut. Arka planda OpenGL ve C++ kullanılması sebebi ile mobil aygıtlarda sizi pek üzmeyecektir.

Evet hızlıca C++ ve QML perspektifinden olaya baktıktan sonra artık bu ikisini birlikte nasıl kullanabileceğimize göz atalım.

C++/QML kullanımı

Evet gelelim bu işi nasıl yapacağımıza. Bu başlıktan itibaren, adım adım ve örnek bir kod üzerinden gidiyor olacağız. Burada geliştirdiğimiz kodlara aşağıdaki adresten de ulaşabilirsiniz:

https://github.com/yazilimperver/QmlCPlusPlusIntegration

Öncelikle, QML uygulamaları, bir çalışma zamanı ortamında çalıştırılmaktadır. Bu çalışma zamanı da C++ kullanılarak QtQml modülü içerisinde geliştirilmiştir. Bu anlamda, ihtiyaç duyacağımız ilk şey QML kodumuzu, bu çalışma zamanı motoruna sağlamak olacak. Bunun için de aşağıdaki kodu kullanacağız:

QML, QT’in “Meta Object System”ini kullandığı için, QML içerisinde C++ kodunu çağırmak, oldukça kolay. Bunu gerçekleştirmek için öncelikle:

  • İlgili C++ sınıfımız QObject‘ten türetilmeli, Q_OBJECT makrosu sınıf tanımı içerisinde olmalıdır:

  • Daha sonra sınıfımızı main.cpp içerisinden aşağıda belirtildiği şekilde kayıt ettirmemiz gerekiyor. Bundan sonra artık BackEndClass bir tip olarak eklenmiş oldu, bu tipi de QML içerisinden kullanmak için “import yazilimperver.example.backend 1.0” eklememiz yeterli olacak.

  • Son tahlilde bu örnek için aşağıdaki QML dosyasını kullanacağız.  Burada BackEndClass sınıfımızın da nasıl QML içerisinde kullanabileceğimizi görebilirsiniz. Aslında diğer bileşenlerden pek bir farkı yok.

Tabi ki işimiz burada bitmedi. Bilakis yeni başlıyoruz. Şimdi geldik, QML ve QT arasındaki etkileşimleri nasıl gerçekleştirebileceğimize. Aslına bakarsanız, “Meta Object System” sayesinde normal QObject‘ten türetilmiş C++ sınıfları ile benzer şekilde kullanabileceğiz. O zaman gelsin sorular. Öncelikle, verileri nasıl paylaşabiliriz?

QML/C++ veri paylaşımı

Qt bizler için temel, QT sınıflarını QML’e de sunmakta, yani QString ve benzeri tipleri kullanmak için özel bir şey yapmanıza gerek yok. Tabi bunları aynı isimler kullanamayabilirsiniz (temel tipler dışında). Bir fikir vermesi açısından temel QT veri tiplerini buraya ekliyorum. Daha detaylı bilgi için https://doc.qt.io/qt-5/qtqml-cppintegration-data.html sayfasına göz atabilirsiniz.

Qt TipiQML Karşılığı
boolbool
unsigned int, intint
doubledouble
float, qrealreal
QStringstring
QUrlurl
QColorcolor
QFontfont
QDateTimedate
QPointQPointFpoint
QSizeQSizeFsize
QRectQRectFrect
QMatrix4x4matrix4x4
QQuaternionquaternion
QVector2DQVector3DQVector4Dvector2dvector3dvector4d
Enums declared with Q_ENUM() or Q_ENUMS()enumeration

Bunlar yanında, sıralı veri tipleri/dizileri de Javascript dizisi olarak kullanılabilmektedir.

Kendi tiplerimizi nasıl kullanacağımıza da zaten baktık. Bunları öncelikle .cpp dosyası içerisinde kaydettiriyoruz ve daha sonra “import” mekanizması ile bunu qml içerisinde de kullanabileceğiz.

QML/C++ arası etkileşim

QML ile C++ arasındaki etkileşimi bir kaç şekilde gerçekleştirebiliyoruz. Temel olarak bu etkileşim tanımladığımız C++ sınıfları üzerinden gerçekleştiriliyor. Bu sınıfı nasıl tanımlayacağımıza yukarıda baktık. QML kodu bu sınıflardaki aşağıdakilere erişebilmektedir:

  • Uygun bir şekilde (bunun nasıl olacağına hemen bakacağız) tanımlanan değişkenler (“properties”),
  • Uygun bir şekilde (bunun da nasıl olacağına hemen bakacağız) tanımlanan metotlar,
  • Tanımlanmış olan slot’lara bağlantı kurup/çağırabiliriz,
  • Tanımlanmış olan sinyalleri tetikleyebiliriz.

Şimdi gelelim bu “uygun bir şekilde” ibarelerini nasıl sağlayacağımıza 🙂

Öncelikle değişkenlere bakalım. Sınfılarınıza ilişkin değişkenlerin QML tarafından kullanılabilmesi için Q_PROPERTY makrosu ile tanımlanmış olmaları gerekmektedir. Hemen bir örneğe bakalım:

Bu tanımlama ile birlikte QML tarafından message değişkenine erişilebilir ve bu değişkene ilişkin değişiklikler de ilgili messageChanged sinyali ile QML tarafına bildirilebilecektir. Şimdi gelelim sinyal ve slot’lar dışındaki metotları QML tarafından kullanabilmek için yapmamız gerekenlere.

Aslında bu da oldukça kolay. Bunun için de Q_INVOKABLE makrosunu kullanıyoruz, basitçe ilgili public metodun önüne bunu eklemeniz yeterli. Bunun için de C++ içerisinde bir sayaç değişkeni ekliyoruz ve bunun arttırılması için bir metot ve sıfırlanması için bir slot tanımlıyoruz:

Son olarak QML tarafını da aşağıdaki gibi güncelleyerek örneğimizi tamamlıyoruz:

Evet arkadaşlar, temel entegrasyon için gerekli olan kısımları sizlere aktarmaya çalıştım. Açıkçası bu zamana kadar, bu basit kullanım benim işimi gördü ama buna ilişkin daha bir çok husus var ki burada daha fazla değinmeyeceğim. Ama ilgili dostlar https://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html bağlantısına bir göz atabilirler.

Bitirmeden önce son bir husustan daha bahsetmek istiyorum. Burada takip ettiğim etkileşim yönteminin yanında https://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html da da bahsedilen farklı yöntemler mevcut. Ben burada özellikle C++ tarafından, direk QML tarafına sinyal ve slot mekanizmaları dışında, fonksiyon ve benzeri mekanizmalarla çok erişmedim, fakat bunlar mümkün. Açıkçası ben, kendi uygulamalarımda sizler ile paylaşmış olduğum yaklaşımı takip ediyorum ama farklı kullanımlarından da haberdar olmakta fayda var.

Bu yazımızın da sonuna geldik. Kodun son haline https://github.com/yazilimperver/QmlCPlusPlusIntegration adresinden ulaşabilirsiniz.

Umarım, QML ile C++ kullanımına ilişkin sizlere bir yol göstermiştir. Bir sonraki yazımda görüşmek dileğiyle, kendinize iyi bakın.

Kaynaklar

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.