KDAB / cxx-qt

Safe interop between Rust and Qt
https://kdab.github.io/cxx-qt/book/
1.05k stars 75 forks source link

Bridge module without QObject type #1033

Closed ahayzen-kdab closed 1 month ago

ahayzen-kdab commented 2 months ago

Discussed in https://github.com/KDAB/cxx-qt/discussions/1032

Originally posted by **SanderVocke** August 13, 2024 Hi there, I'm finding that cxx-qt does not seem to allow defining a bridge module that does not have a `#[qobject]`-type in it. The reason seems to be that automoc is run on the resulting C++ files, and they error out when there are no Q_OBJECT types in the headers. For this reason, I am having to add dummy QObject types to all the bridge modules that I am making with e.g. some trivial types in them. Am I missing something? Example: ```rust #[cxx_qt::bridge(cxx_file_stem = "shoop_rust_callable")] pub mod ffi { unsafe extern "C++" { include!("cxx-qt-lib/qvariant.h"); type QVariant = cxx_qt_lib::QVariant; } unsafe extern "C++" { include!("cxx-qt-shoop/shoop_rust_callable.h"); type ShoopRustCallable = type_shoop_rust_callable::ShoopRustCallableRust; #[rust_name = "qvariant_can_convert_shoop_rust_callable"] fn qvariantCanConvertShoopRustCallable(variant: &QVariant) -> bool; #[rust_name = "register_metatype_shoop_rust_callable"] fn registerMetatypeShoopRustCallable(name : &mut String); } #[namespace = "rust::cxxqtlib1::qvariant"] unsafe extern "C++" { include!("cxx-qt-lib/qvariant.h"); #[rust_name = "qvariant_construct_shoop_rust_callable"] fn qvariantConstruct(value: &ShoopRustCallable) -> QVariant; #[rust_name = "qvariant_value_or_default_shoop_rust_callable"] fn qvariantValueOrDefault(variant: &QVariant) -> ShoopRustCallable; } extern "RustQt" { #[qobject] type Dummy= super::DummyRust; } } use ffi::*; #[derive(Default)] pub struct DummyRust {} (...) ``` This works, but fails as soon as the `Dummy` and `DummyRust` types are removed.
BenFordTytherington commented 2 months ago

When I've tried to reproduce this locally, I got this error message:

  thread 'main' panicked at /home/ben/cxx-qt/crates/qt-build-utils/src/lib.rs:860:17:
  qmltyperegistrar failed for com.kdab.cxx_qt.demo:
  Error: /home/ben/cxx-qt/target/debug/build/qml-minimal-no-cmake-2e43c9623c960347/out/moc_shoop_rust_callable.cxxqt.h.cpp.json:: Failed to parse JSON: 5 illegal value

Is this similar to what you found?

SanderVocke commented 2 months ago

@BenFordTytherington Sorry for the late response - I accidentally turned off notifications. Yes, that's exactly the error I got. I interpret that as trying to run moc on a C++ file without any moc-able objects in it.

LeonMatthesKDAB commented 2 months ago

Hm, that actually seems like it's not moc that's the issue, but rather qmltyperegistrar.

Although the two are somewhat related, that's not the same thing. First we run moc to expand any of the Qt macros. I think this can handle C++ files without a Q_OBJECT, as it should handle that in a C++ project as well. However, we then run qmltyperegistrar to create a QML plugin that automatically registers all the necessary types.

This then fails, as we seem to pass it the wrong data. Probably because it's trying to register a type from a file that doesn' have one.

You may be able to get around this by defining the bridge not in a QML module, but just as a normal bridge in the CxxQtBuilder.

But we should of course fix this for QML modules as well.