rust-qt / ritual

Use C++ libraries from Rust
Apache License 2.0
1.22k stars 49 forks source link

Some class miss its constructor, Qt5.9.1 #63

Closed aristotle9 closed 4 years ago

aristotle9 commented 6 years ago

I use this wonderful tool to generate rust bindings of Qt5.9.1. The Qt sdk is installed by brew. First I fixed a link err, which is caused by the incorrect is_framework determination. It's works. Then I find some class miss its new() method. One of the class is Widget, link to my output source.

Riateche commented 6 years ago

You can run the generator with --debug-logging=save and then look at log/debug_parser_skips.log file in the cache directory. It should explain why the methods are missing.

Can you share what changes related to frameworks did you need to do? Does your Qt installation contain frameworks or libraries?

I'm currently changing implementation to allow supporting all Qt versions at once. Hopefully it will make parser inconsistency issues less critical. I don't know how long it will take, though.

aristotle9 commented 6 years ago

debug_parser_skips.log

...
Method is removed: Qt::Orientations<Qt::Orientation> QSizePolicy::expandingDirections() const: unknown type: Qt::Orientations
Method is removed: QFlags<QSizePolicy::ControlType> operator|(QFlags::enum_type f1, QFlags::enum_type f2): unknown type: QFlags::enum_type
Method is removed: QFlags<QSizePolicy::ControlType> operator|(QFlags::enum_type f1, QFlags<QSizePolicy::ControlType> f2): unknown type: QFlags::enum_type
Method is removed: QIncompatibleFlag operator|(QFlags::enum_type f1, int f2): unknown type: QIncompatibleFlag
Method is removed: private QWidgetPrivate* QWidget::d_func(): unknown type: QWidgetPrivate
Method is removed: private const QWidgetPrivate* QWidget::d_func() const: unknown type: QWidgetPrivate
Method is removed: [constructor] void QWidget::QWidget(QWidget* parent = ?, Qt::WindowFlags<Qt::WindowType> f = ?): unknown type: Qt::WindowFlags
Method is removed: void QWidget::grabGesture(Qt::GestureType type, Qt::GestureFlags<Qt::GestureFlag> flags = ?): unknown type: Qt::GestureFlags
Method is removed: Qt::WindowStates<Qt::WindowState> QWidget::windowState() const: unknown type: Qt::WindowStates
Method is removed: void QWidget::setWindowState(Qt::WindowStates<Qt::WindowState> state): unknown type: Qt::WindowStates
...

It seems like some complex defines failed to parse.

Can you share what changes related to frameworks did you need to do? Does your Qt installation contain frameworks or libraries?

I just adjust the detect order. Here is my codes.

cpp_to_rust/qt_generator/qt_generator_common/src/lib.rs

...
/// Detects properties of current Qt installation using `qmake` command line utility.
pub fn get_installation_data(sublib_name: &str) -> Result<InstallationData> {
  let qt_version = run_qmake_string_query("QT_VERSION")?;
  log::status(format!("QT_VERSION = \"{}\"", qt_version));
  log::status("Detecting Qt directories");

  let root_include_path = run_qmake_query("QT_INSTALL_HEADERS")?;
  log::status(format!("QT_INSTALL_HEADERS = \"{}\"", root_include_path.display()));
  let lib_path = run_qmake_query("QT_INSTALL_LIBS")?;
  log::status(format!("QT_INSTALL_LIBS = \"{}\"", lib_path.display()));
  let docs_path = run_qmake_query("QT_INSTALL_DOCS")?;
  log::status(format!("QT_INSTALL_DOCS = \"{}\"", docs_path.display()));
  let folder_name = lib_folder_name(sublib_name);
  let dir = lib_path.with_added(format!("{}.framework/Headers", folder_name));
  if dir.exists() {
    Ok(InstallationData {
         root_include_path: root_include_path,
         lib_path: lib_path,
         docs_path: docs_path,
         lib_include_path: dir,
         is_framework: true,
         qt_version: qt_version,
       })
  } else {
    let dir2 = root_include_path.with_added(&folder_name);
    if dir2.exists() {
      Ok(InstallationData {
           root_include_path: root_include_path,
           lib_path: lib_path,
           docs_path: docs_path,
           lib_include_path: dir2,
           is_framework: false,
           qt_version: qt_version,
         })
    } else {
      Err(format!("extra header dir not found (tried: {}, {})",
                  dir.display(),
                  dir2.display())
              .into())
    }
  }
}
...

and my directory struct of the qt5.9.1 sdk library installed by home brew:

/usr/local/Cellar/qt/5.9.1/include
$ ls -l
total 512
lrwxr-xr-x   1 user  admin    38 Jun 29 08:06 Qt3DAnimation -> ../lib/Qt3DAnimation.framework/Headers
lrwxr-xr-x   1 user  admin    33 Jun 29 08:06 Qt3DCore -> ../lib/Qt3DCore.framework/Headers
lrwxr-xr-x   1 user  admin    35 Jun 29 08:06 Qt3DExtras -> ../lib/Qt3DExtras.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 Qt3DInput -> ../lib/Qt3DInput.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 Qt3DLogic -> ../lib/Qt3DLogic.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 Qt3DQuick -> ../lib/Qt3DQuick.framework/Headers
lrwxr-xr-x   1 user  admin    43 Jun 29 08:06 Qt3DQuickAnimation -> ../lib/Qt3DQuickAnimation.framework/Headers
lrwxr-xr-x   1 user  admin    40 Jun 29 08:06 Qt3DQuickExtras -> ../lib/Qt3DQuickExtras.framework/Headers
lrwxr-xr-x   1 user  admin    39 Jun 29 08:06 Qt3DQuickInput -> ../lib/Qt3DQuickInput.framework/Headers
lrwxr-xr-x   1 user  admin    40 Jun 29 08:06 Qt3DQuickRender -> ../lib/Qt3DQuickRender.framework/Headers
lrwxr-xr-x   1 user  admin    41 Jun 29 08:06 Qt3DQuickScene2D -> ../lib/Qt3DQuickScene2D.framework/Headers
lrwxr-xr-x   1 user  admin    35 Jun 29 08:06 Qt3DRender -> ../lib/Qt3DRender.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtAccessibilitySupport
lrwxr-xr-x   1 user  admin    36 Jun 29 08:06 QtBluetooth -> ../lib/QtBluetooth.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtCglSupport
lrwxr-xr-x   1 user  admin    33 Jun 29 08:06 QtCharts -> ../lib/QtCharts.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtClipboardSupport
lrwxr-xr-x   1 user  admin    37 Jun 29 08:06 QtConcurrent -> ../lib/QtConcurrent.framework/Headers
lrwxr-xr-x   1 user  admin    31 Jun 29 08:06 QtCore -> ../lib/QtCore.framework/Headers
lrwxr-xr-x   1 user  admin    31 Jun 29 08:06 QtDBus -> ../lib/QtDBus.framework/Headers
lrwxr-xr-x   1 user  admin    44 Jun 29 08:06 QtDataVisualization -> ../lib/QtDataVisualization.framework/Headers
lrwxr-xr-x   1 user  admin    35 Jun 29 08:06 QtDesigner -> ../lib/QtDesigner.framework/Headers
lrwxr-xr-x   1 user  admin    45 Jun 29 08:06 QtDesignerComponents -> ../lib/QtDesignerComponents.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtDeviceDiscoverySupport
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtEventDispatcherSupport
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtFbSupport
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtFontDatabaseSupport
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 QtGamepad -> ../lib/QtGamepad.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtGraphicsSupport
lrwxr-xr-x   1 user  admin    30 Jun 29 08:06 QtGui -> ../lib/QtGui.framework/Headers
lrwxr-xr-x   1 user  admin    31 Jun 29 08:06 QtHelp -> ../lib/QtHelp.framework/Headers
lrwxr-xr-x   1 user  admin    35 Jun 29 08:06 QtLocation -> ../lib/QtLocation.framework/Headers
lrwxr-xr-x   1 user  admin    36 Jun 29 08:06 QtMacExtras -> ../lib/QtMacExtras.framework/Headers
lrwxr-xr-x   1 user  admin    37 Jun 29 08:06 QtMultimedia -> ../lib/QtMultimedia.framework/Headers
lrwxr-xr-x   1 user  admin    44 Jun 29 08:06 QtMultimediaQuick_p -> ../lib/QtMultimediaQuick_p.framework/Headers
lrwxr-xr-x   1 user  admin    44 Jun 29 08:06 QtMultimediaWidgets -> ../lib/QtMultimediaWidgets.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 QtNetwork -> ../lib/QtNetwork.framework/Headers
lrwxr-xr-x   1 user  admin    38 Jun 29 08:06 QtNetworkAuth -> ../lib/QtNetworkAuth.framework/Headers
lrwxr-xr-x   1 user  admin    30 Jun 29 08:06 QtNfc -> ../lib/QtNfc.framework/Headers
lrwxr-xr-x   1 user  admin    33 Jun 29 08:06 QtOpenGL -> ../lib/QtOpenGL.framework/Headers
drwxr-xr-x   8 user  admin   272 Jun 29 08:06 QtOpenGLExtensions
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtPacketProtocol
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtPlatformCompositorSupport
drwxr-xr-x  30 user  admin  1020 Jun 29 08:06 QtPlatformHeaders
lrwxr-xr-x   1 user  admin    38 Jun 29 08:06 QtPositioning -> ../lib/QtPositioning.framework/Headers
lrwxr-xr-x   1 user  admin    39 Jun 29 08:06 QtPrintSupport -> ../lib/QtPrintSupport.framework/Headers
lrwxr-xr-x   1 user  admin    37 Jun 29 08:06 QtPurchasing -> ../lib/QtPurchasing.framework/Headers
lrwxr-xr-x   1 user  admin    30 Jun 29 08:06 QtQml -> ../lib/QtQml.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtQmlDebug
lrwxr-xr-x   1 user  admin    32 Jun 29 08:06 QtQuick -> ../lib/QtQuick.framework/Headers
lrwxr-xr-x   1 user  admin    41 Jun 29 08:06 QtQuickControls2 -> ../lib/QtQuickControls2.framework/Headers
lrwxr-xr-x   1 user  admin    41 Jun 29 08:06 QtQuickParticles -> ../lib/QtQuickParticles.framework/Headers
lrwxr-xr-x   1 user  admin    42 Jun 29 08:06 QtQuickTemplates2 -> ../lib/QtQuickTemplates2.framework/Headers
lrwxr-xr-x   1 user  admin    36 Jun 29 08:06 QtQuickTest -> ../lib/QtQuickTest.framework/Headers
lrwxr-xr-x   1 user  admin    39 Jun 29 08:06 QtQuickWidgets -> ../lib/QtQuickWidgets.framework/Headers
lrwxr-xr-x   1 user  admin    40 Jun 29 08:06 QtRemoteObjects -> ../lib/QtRemoteObjects.framework/Headers
lrwxr-xr-x   1 user  admin    36 Jun 29 08:06 QtRepParser -> ../lib/QtRepParser.framework/Headers
lrwxr-xr-x   1 user  admin    33 Jun 29 08:06 QtScript -> ../lib/QtScript.framework/Headers
lrwxr-xr-x   1 user  admin    38 Jun 29 08:06 QtScriptTools -> ../lib/QtScriptTools.framework/Headers
lrwxr-xr-x   1 user  admin    32 Jun 29 08:06 QtScxml -> ../lib/QtScxml.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 QtSensors -> ../lib/QtSensors.framework/Headers
lrwxr-xr-x   1 user  admin    36 Jun 29 08:06 QtSerialBus -> ../lib/QtSerialBus.framework/Headers
lrwxr-xr-x   1 user  admin    37 Jun 29 08:06 QtSerialPort -> ../lib/QtSerialPort.framework/Headers
lrwxr-xr-x   1 user  admin    30 Jun 29 08:06 QtSql -> ../lib/QtSql.framework/Headers
lrwxr-xr-x   1 user  admin    30 Jun 29 08:06 QtSvg -> ../lib/QtSvg.framework/Headers
lrwxr-xr-x   1 user  admin    31 Jun 29 08:06 QtTest -> ../lib/QtTest.framework/Headers
lrwxr-xr-x   1 user  admin    39 Jun 29 08:06 QtTextToSpeech -> ../lib/QtTextToSpeech.framework/Headers
drwxr-xr-x   7 user  admin   238 Jun 29 08:06 QtThemeSupport
lrwxr-xr-x   1 user  admin    35 Jun 29 08:06 QtUiPlugin -> ../lib/QtUiPlugin.framework/Headers
drwxr-xr-x   9 user  admin   306 Jun 29 08:06 QtUiTools
lrwxr-xr-x   1 user  admin    37 Jun 29 08:06 QtWebChannel -> ../lib/QtWebChannel.framework/Headers
lrwxr-xr-x   1 user  admin    36 Jun 29 08:06 QtWebEngine -> ../lib/QtWebEngine.framework/Headers
lrwxr-xr-x   1 user  admin    40 Jun 29 08:06 QtWebEngineCore -> ../lib/QtWebEngineCore.framework/Headers
lrwxr-xr-x   1 user  admin    43 Jun 29 08:06 QtWebEngineWidgets -> ../lib/QtWebEngineWidgets.framework/Headers
lrwxr-xr-x   1 user  admin    37 Jun 29 08:06 QtWebSockets -> ../lib/QtWebSockets.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 QtWebView -> ../lib/QtWebView.framework/Headers
lrwxr-xr-x   1 user  admin    34 Jun 29 08:06 QtWidgets -> ../lib/QtWidgets.framework/Headers
lrwxr-xr-x   1 user  admin    30 Jun 29 08:06 QtXml -> ../lib/QtXml.framework/Headers
lrwxr-xr-x   1 user  admin    38 Jun 29 08:06 QtXmlPatterns -> ../lib/QtXmlPatterns.framework/Headers
o01eg commented 6 years ago

Same for Qt 5.7.1 with clang 3.9.1 on linux.

o01eg commented 6 years ago

Looks like it because of qt_core fails. qt_core/log/debug_parser.log https://gist.github.com/o01eg/6064fb33abb6914ba0feb770c77c2bbd

Riateche commented 6 years ago

Looks like Qt::WindowFlags type is parsed successfully in qt_core, but when the generator works on qt_widgets, it doesn't have this information available. What are the command line arguments to qt_generator that you use when generating qt_core, qt_gui and qt_widgets?

o01eg commented 6 years ago

Not sure if it successful:

Failed to tokenize method operator| at SourceRange { start: SourceLocation { file: Some(File { path: "/usr/include/qt5/QtCore/qnamespace.h" }), line: 1758, column: 1, offset: 53192 }, end: SourceLocation { file: Some(File { path: "/usr/include/qt5/QtCore/qnamespace.h" }), line: 1758, column: 47, offset: 53238 } }
The code extracted directly from header: "Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowFlags)"

Args are:

CLANG_SYSTEM_INCLUDE_PATH=/usr/lib64/clang/3.9.1/include/ QT_SELECT=5 cargo run --release -- -c /tmp/_qt_cache -C 0 --debug-logging save -l core gui widgets ui_tools -o /tmp/qt-test001/
aristotle9 commented 6 years ago

What are the command line arguments to qt_generator that you use when generating qt_core, qt_gui and qt_widgets?

export PATH=$PATH:/usr/local/Cellar/qt/5.9.1/bin
CLANG_SYSTEM_INCLUDE_PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-migrator/sdks/MacOSX.sdk/usr/include DYLD_LIBRARY_PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib ../cpp_to_rust/qt_generator/qt_generator/target/release/qt_generator -c cache -o qt_5.8.0 --libs all --debug-logging=save
Riateche commented 6 years ago

The framework detection issue should be fixed now.

Source of the main issue is not clear yet.

snuk182 commented 5 years ago

The following start of the QtCore headers parse

Failed to parse class: QIntegerForSizeof
entity: Entity { kind: ClassTemplate, display_name: Some("QIntegerForSizeof<T>"), location: Some(SourceLocation { file: Some(File { path: "/usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h" }), line: 448, column: 27, offset: 14974 }) }
error: Can't parse base class type: Template argument of unexposed type is not parsed: sizeof(T): Unexposed type has a declaration but is too complex: sizeof(T)

Failed to parse class: QOverload
entity: Entity { kind: ClassTemplate, display_name: Some("QOverload<Args>"), location: Some(SourceLocation { file: Some(File { path: "/usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h" }), line: 1088, column: 8, offset: 37613 }) }
error: Can't parse base class type: Template argument of unexposed type is not parsed: Args...: Unexposed type has a declaration but is too complex: Args...

failed to parse class field: failed to parse field type: QFlags::i::i
Failed to parse class: QAtomicOpsSupport
entity: Entity { kind: ClassTemplate, display_name: Some("QAtomicOpsSupport<int>"), location: Some(SourceLocation { file: Some(File { path: "/usr/include/x86_64-linux-gnu/qt5/QtCore/qgenericatomic.h" }), line: 56, column: 22, offset: 2250 }) }
error: Non-type template parameter is not supported

Failed to parse class: QAtomicTraits
entity: Entity { kind: ClassTemplate, display_name: Some("QAtomicTraits<N>"), location: Some(SourceLocation { file: Some(File { path: "/usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h" }), line: 75, column: 25, offset: 3137 }) }
error: Non-type template parameter is not supported

Failed to parse class: QGlobalStatic
entity: Entity { kind: ClassTemplate, display_name: Some("QGlobalStatic<T, innerFunction, guard>"), location: Some(SourceLocation { file: Some(File { path: "/usr/include/x86_64-linux-gnu/qt5/QtCore/qglobalstatic.h" }), line: 128, column: 8, offset: 6041 }) }
error: Non-type template parameter is not supported

leads to

Not planned to support:

    Advanced template usage, like types with integer template arguments.
    Template partial specializations.
    Template methods and functions.

because (I guess) these cannot be directly translated to the Rust entities, as Rust lacks them, at least without unwrapping the templated code.

Riateche commented 5 years ago

It's correct that there are types we're not going to support, and things like QIntegerForSizeof and QAtomicTraits are among them. Luckily, Qt doesn't use advanced templates heavily, so the majority of Qt's public API will be available.

plyhun commented 5 years ago

Is there a way then to improve Rust-Qt to be usable with the recent Qt versions? The generator from master cannot chew the templated types, and the crates version is old and leads to the random runtime segfaults.

Riateche commented 5 years ago

The master version does support template types. However, its results are quite unstable across platforms, so some APIs may be missing. The new version is still in development, and the plan is to support newer Qt versions for it.

If you experience segfaults in the crates.io version, I would appreciate an issue that shows concrete code that produces it. Unfortunately, the wrapper is really unsafe in Rust's terms, so it's very easy to produce a segfault by incorrectly using C++-based APIs.

plyhun commented 5 years ago

During trying to get the simplest code for segfaults reproduction I have accidentally fixed it. Did not use the create_and_exit method from the tutorial and was dropping args all the time.

lilianmoraru commented 4 years ago

@Riateche I see that you updated the "install_qt.py" script with Qt 5.13.0. Does ritual support Qt 5.13.0? On docs.io it says that the crate was generated against Qt 5.8.0(if it supports Qt 5.13.0, could you please update it against Qt 5.13.0?). Would really like to use that seamless ETC support in QtQuick :)

Riateche commented 4 years ago

Qt 5.13 is currently supported, but new versions are not published on crates.io yet. I'm working on it.

Riateche commented 4 years ago

New version supporting Qt 5.13 is published on crates.io.

In the new version, the recommended way is to use generated crates that support a variety of Qt versions and platforms, so lack of some random functions shouldn't be a thing anymore.