Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions crates/cxx-qt-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,22 +1065,22 @@ impl CxxQtBuilder {
// `extern "C"` as Q_INIT_RESOURCES needs name mangling, which doesn't happen if it's
// called within an `extern "C"` function.
// So add a static do_init function that we then call from the actual initializer function.
//
// Use atomic operations for single initialization - this is simpler than std::call_once
// and works reliably on all platforms including MinGW.
let init_function = format!(
r#"
#include <mutex>
#include <atomic>

{declarations}

static bool do_init() {{
static std::once_flag flag;
std::call_once(flag, []() {{
{calls}
}});
return true;
}}
static std::atomic<bool> initialized{{false}};

extern "C" bool {init_fun}() {{
return do_init();
if (!initialized.exchange(true, std::memory_order_acq_rel)) {{
{calls}
}}
return true;
}}
"#,
declarations = declarations.join("\n"),
Expand All @@ -1103,6 +1103,9 @@ extern "C" bool {init_fun}() {{
export_path: Option<PathBuf>,
key: &str,
) {
// Collect the private initializers so we can iterate multiple times
let private_initializers: Vec<_> = private_initializers.into_iter().collect();

// Build the initializers themselves into the main library.
self.cc_builder
.file(
Expand All @@ -1113,7 +1116,7 @@ extern "C" bool {init_fun}() {{
)
.files(
private_initializers
.into_iter()
.iter()
.filter_map(|initializer| initializer.file.as_ref()),
);

Expand All @@ -1124,16 +1127,23 @@ extern "C" bool {init_fun}() {{
let includes: &[&str] = &[]; // <-- Needed for type annotations
Self::setup_cc_builder(&mut init_call_builder, includes);

let declaration = public_initializer
.init_declaration
.clone()
.unwrap_or_default();
let call = public_initializer
.init_call
.clone()
.expect("Public initializer must be callable!");

// Static initialization to trigger the init chain. The actual metatype registration
// is handled by Q_COREAPP_STARTUP_FUNCTION in the init.cpp files, so the init
// functions themselves are lightweight (just return true).
let init_call = format!(
"{declaration}\nstatic const bool do_init_{key} = {init_call}",
declaration = public_initializer
.init_declaration
.clone()
.unwrap_or_default(),
init_call = public_initializer
.init_call
.clone()
.expect("Public initializer must be callable!"),
declaration = declaration,
init_call = call,
key = key,
);

let init_file = dir::initializers(key).join("call-initializers.cpp");
Expand Down
19 changes: 13 additions & 6 deletions crates/cxx-qt-lib/src/core/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@
#include <cxx-qt-lib/qset.h>
#include <cxx-qt-lib/qvector.h>

#include <mutex>
#include <QtCore/QCoreApplication>

extern "C" bool
init_cxx_qt_lib_core()
static void do_register_core_types()
{
static std::once_flag flag;
std::call_once(flag, []() {
qRegisterMetaType<::QHash_i32_QByteArray>("QHash_i32_QByteArray");
// Ensure that QHash<QString, QVariant> (aka QVariantHash) is registered
// otherwise it cannot be used in QML
Expand Down Expand Up @@ -115,7 +112,17 @@ init_cxx_qt_lib_core()
qRegisterMetaType<::QVector_u16>("QVector_u16");
qRegisterMetaType<::QVector_u32>("QVector_u32");
qRegisterMetaType<::QVector_u64>("QVector_u64");
});
}

// Use Q_COREAPP_STARTUP_FUNCTION to defer registration until QCoreApplication
// is created. This is Qt's recommended approach for type registration and
// ensures proper initialization order on all platforms.
Q_COREAPP_STARTUP_FUNCTION(do_register_core_types)

extern "C" bool
init_cxx_qt_lib_core()
{
// Registration is handled automatically via Q_COREAPP_STARTUP_FUNCTION
// when QCoreApplication is constructed.
return true;
}
19 changes: 13 additions & 6 deletions crates/cxx-qt-lib/src/gui/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@
#include <cxx-qt-lib/qlist.h>
#include <cxx-qt-lib/qvector.h>

#include <mutex>
#include <QtCore/QCoreApplication>

extern "C" bool
init_cxx_qt_lib_gui()
static void do_register_gui_types()
{
static std::once_flag flag;
std::call_once(flag, []() {
qRegisterMetaType<::QList_QColor>("QList_QColor");
qRegisterMetaType<::QVector_QColor>("QVector_QColor");
});
}

// Use Q_COREAPP_STARTUP_FUNCTION to defer registration until QCoreApplication
// is created. This is Qt's recommended approach for type registration.
Q_COREAPP_STARTUP_FUNCTION(do_register_gui_types)

extern "C" bool
init_cxx_qt_lib_gui()
{
// Registration is handled automatically via Q_COREAPP_STARTUP_FUNCTION
// when QCoreApplication is constructed.
return true;
}
20 changes: 13 additions & 7 deletions crates/cxx-qt/src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@

// For versions less than Qt 6 we need to manually register the std numerics
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
#include <QtCore/QMetaType>

#include <QtCore/QCoreApplication>
#include <QtCore/QMetaType>
#include <cstdint>
#include <mutex>

extern "C" bool
init_cxx_qt_core()
static void do_register_cxx_qt_core_types()
{
static std::once_flag flag;
std::call_once(flag, []() {
// If we are using Qt 5 then register std numbers as a type for use in QML.
//
// See also:
Expand All @@ -33,8 +30,17 @@ init_cxx_qt_core()
qRegisterMetaType<::std::uint16_t>("::std::uint16_t");
qRegisterMetaType<::std::uint32_t>("::std::uint32_t");
qRegisterMetaType<::std::uint64_t>("::std::uint64_t");
});
}

// Use Q_COREAPP_STARTUP_FUNCTION to defer registration until QCoreApplication
// is created. This is Qt's recommended approach for type registration.
Q_COREAPP_STARTUP_FUNCTION(do_register_cxx_qt_core_types)

extern "C" bool
init_cxx_qt_core()
{
// Registration is handled automatically via Q_COREAPP_STARTUP_FUNCTION
// when QCoreApplication is constructed.
return true;
}

Expand Down
Loading