首先推薦幾篇博客
1.深入解析QML引擎, 第1部分:QML文件加載
https://www.cnblogs.com/wzxNote/p/10569535.html
2.深入解析QML引擎, 第2部分: 綁定(Bindings)
https://www.cnblogs.com/wzxNote/p/10569542.html
3.深入解析QML引擎, 第3部分: 綁定類型
https://www.cnblogs.com/wzxNote/p/10569547.html
4.深入解析QML引擎, 第4部分: 自定義解析器
https://www.cnblogs.com/wzxNote/p/10569554.html
5.QML引擎的演進,第一部分
https://blog.qt.io/cn/2013/04/18/evolution-of-the-qml-engine-part-1/
這四篇博文由淺入深的講述了QML引擎的實現機制。
1.QML文件的加載過程涉及到QML文件的解析,js代碼的解釋;
2.綁定講解了QML的屬性綁定,通過VME模塊創建的指令.生成一個QQmlBinding對象,傳入js函數,vme再把傳入的函數生成一個v8:Function函數(翻譯成二進制的機器碼)。通過運行編譯后的V8::Function代碼來對綁定進行求值,再由V8引擎通過Qt里的包裹類來訪問對象和屬性,然后將求的值賦給目標屬性。
3.因為QV8Bindings把QML文件中所有的綁定組織在一起,所以可以花費更少的內存,並只執行一次編譯。
歸納起來,有3個綁定類型,都是從QQmlAbstractBinding繼承:
1). QV4Bindings::Binding
2). QV8Bindings::Binding
3). QQmlBinding
QV4Bindings是最快的,因為其使用了自定義的字節碼引擎。QV8Bindings和QQmlBinding都是使用V8 JS引擎執行,但QV8Bindings將所有的綁定組織在一起,一次性編譯,然而QQmlBindings會在每個QML組件實例化過程中一個一個地進行編譯。
4.多個對象模型
當前的QML引擎使用V8 JavaScript引擎來執行屬性綁定。每個QML項內部有幾個不同的表示。一個面向V8(使用公開的V8 API),一個面向QML引擎,還有一個作為QObject暴露給原生Qt。這里的問題是需要QML引擎來同步這些不同的表示,導致了大量的中間代碼和相當高的內存消耗來維持這些不同的表示。
QML調用js函數的調用堆棧如下:
QML調用C++函數的調用堆棧如下:
person類(js調用的c++函數所在的類)的函數最后的調用過程為
void Person::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) { if (_c == QMetaObject::InvokeMetaMethod) { auto *_t = static_cast<Person *>(_o); Q_UNUSED(_t) switch (_id) { case 0: _t->walk(); break; case 1: { bool _r = _t->eat((*reinterpret_cast< const QString(*)>(_a[1]))); if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = std::move(_r); } break; default: ; } } }