-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bindings for QtMsgType, QMessageLogContext and qt_message_output
This allows Rust and CXX-Qt applications to send messages to the Qt logger.
- Loading branch information
Showing
6 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// clang-format off | ||
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]> | ||
// clang-format on | ||
// SPDX-FileContributor: Joshua Goins <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
#pragma once | ||
|
||
#include "rust/cxx.h" | ||
#include <QDebug> | ||
#include <QtCore/qlogging.h> | ||
|
||
QMessageLogContext | ||
construct_qmessagelogcontext(const char* fileName, | ||
int lineNumber, | ||
const char* functionName, | ||
const char* categoryName); | ||
|
||
int | ||
qmessagelogcontext_line(const QMessageLogContext& context); | ||
|
||
const char* | ||
qmessagelogcontext_file(const QMessageLogContext& context); | ||
|
||
const char* | ||
qmessagelogcontext_function(const QMessageLogContext& context); | ||
|
||
const char* | ||
qmessagelogcontext_category(const QMessageLogContext& context); | ||
|
||
// Define namespace otherwise we hit a GCC bug | ||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 | ||
namespace rust { | ||
|
||
template<> | ||
struct IsRelocatable<QMessageLogContext> : ::std::true_type | ||
{}; | ||
|
||
} // namespace rust |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// clang-format off | ||
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]> | ||
// clang-format on | ||
// SPDX-FileContributor: Joshua Goins <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
#include "cxx-qt-lib/qtlogging.h" | ||
|
||
#include <cxx-qt-lib/assertion_utils.h> | ||
|
||
// QMessageLogContext has three "const char*" members for line, category, etc | ||
// https://codebrowser.dev/qt5/qtbase/src/corelib/global/qlogging.h.html#QMessageLogContext | ||
assert_alignment_and_size(QMessageLogContext, { | ||
int version; | ||
int line; | ||
const char* file; | ||
const char* function; | ||
const char* category; | ||
}); | ||
|
||
static_assert(!::std::is_trivially_copy_assignable<QMessageLogContext>::value); | ||
static_assert( | ||
!::std::is_trivially_copy_constructible<QMessageLogContext>::value); | ||
static_assert(::std::is_trivially_destructible<QMessageLogContext>::value); | ||
|
||
QMessageLogContext | ||
construct_qmessagelogcontext(const char* fileName, | ||
int lineNumber, | ||
const char* functionName, | ||
const char* categoryName) | ||
{ | ||
return QMessageLogContext(fileName, lineNumber, functionName, categoryName); | ||
} | ||
|
||
int | ||
qmessagelogcontext_line(const QMessageLogContext& context) | ||
{ | ||
return context.line; | ||
} | ||
|
||
const char* | ||
qmessagelogcontext_file(const QMessageLogContext& context) | ||
{ | ||
return context.file; | ||
} | ||
|
||
const char* | ||
qmessagelogcontext_function(const QMessageLogContext& context) | ||
{ | ||
return context.function; | ||
} | ||
|
||
const char* | ||
qmessagelogcontext_category(const QMessageLogContext& context) | ||
{ | ||
return context.category; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]> | ||
// SPDX-FileContributor: Joshua Goins <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
use cxx::{type_id, ExternType}; | ||
use std::ffi::c_char; | ||
use std::ffi::CStr; | ||
use std::marker::PhantomData; | ||
|
||
#[cxx::bridge] | ||
mod ffi { | ||
/// The level the message is sent to the message handler at. | ||
#[repr(i32)] | ||
enum QtMsgType { | ||
/// A debug message. | ||
QtDebugMsg = 0, | ||
/// An info message. | ||
QtInfoMsg = 4, | ||
/// A warning message. | ||
QtWarningMsg = 1, | ||
/// A fatal message. | ||
QtFatalMsg = 3, | ||
/// A critical message. | ||
QtCriticalMsg = 2, | ||
} | ||
|
||
unsafe extern "C++" { | ||
include!("cxx-qt-lib/qstring.h"); | ||
type QString = crate::QString; | ||
|
||
include!("cxx-qt-lib/qtlogging.h"); | ||
type QMessageLogContext<'a> = crate::QMessageLogContext<'a>; | ||
type QtMsgType; | ||
|
||
/// Outputs a message in the Qt message handler. | ||
fn qt_message_output(msgType: QtMsgType, context: &QMessageLogContext, string: &QString); | ||
|
||
#[cxx_name = "qmessagelogcontext_line"] | ||
#[doc(hidden)] | ||
fn line(context: &QMessageLogContext) -> i32; | ||
|
||
#[cxx_name = "qmessagelogcontext_file"] | ||
#[doc(hidden)] | ||
unsafe fn file(context: &QMessageLogContext) -> *const c_char; | ||
|
||
#[cxx_name = "qmessagelogcontext_function"] | ||
#[doc(hidden)] | ||
unsafe fn function(context: &QMessageLogContext) -> *const c_char; | ||
|
||
#[cxx_name = "qmessagelogcontext_category"] | ||
#[doc(hidden)] | ||
unsafe fn category(context: &QMessageLogContext) -> *const c_char; | ||
} | ||
|
||
#[namespace = "rust::cxxqtlib1"] | ||
unsafe extern "C++" { | ||
include!("cxx-qt-lib/common.h"); | ||
|
||
#[doc(hidden)] | ||
#[rust_name = "construct_qmessagelogcontext"] | ||
unsafe fn construct( | ||
file_name: *const c_char, | ||
line_number: i32, | ||
function_name: *const c_char, | ||
category_name: *const c_char, | ||
) -> QMessageLogContext<'static>; | ||
} | ||
} | ||
|
||
/// The QMessageLogContext struct defines the context passed to the Qt message handler. | ||
#[repr(C)] | ||
#[derive(Clone, Copy)] | ||
pub struct QMessageLogContext<'a> { | ||
version: i32, | ||
line: i32, | ||
file: *const c_char, | ||
function: *const c_char, | ||
category: *const c_char, | ||
_phantom: PhantomData<&'a c_char>, | ||
} | ||
|
||
impl<'a> QMessageLogContext<'a> { | ||
pub fn new( | ||
file: &'a CStr, | ||
line: i32, | ||
function: &'a CStr, | ||
category: &'a CStr, | ||
) -> QMessageLogContext<'a> { | ||
unsafe { | ||
ffi::construct_qmessagelogcontext( | ||
file.as_ptr(), | ||
line, | ||
function.as_ptr(), | ||
category.as_ptr(), | ||
) | ||
} | ||
} | ||
|
||
/// The line number given to the message handler. | ||
pub fn line(&self) -> i32 { | ||
ffi::line(self) | ||
} | ||
|
||
/// The file path given to the message handler. | ||
pub fn file(&self) -> &'a CStr { | ||
unsafe { CStr::from_ptr(ffi::file(self)) } | ||
} | ||
|
||
/// The name of the function given to the message handler. | ||
pub fn function(&self) -> &'a CStr { | ||
unsafe { CStr::from_ptr(ffi::function(self)) } | ||
} | ||
|
||
/// The category given to the message handler. | ||
pub fn category(&self) -> &'a CStr { | ||
unsafe { CStr::from_ptr(ffi::category(self)) } | ||
} | ||
} | ||
|
||
// Safety: | ||
// | ||
// Static checks on the C++ side ensure that QMessageLogContext is trivial. | ||
unsafe impl ExternType for QMessageLogContext<'_> { | ||
type Id = type_id!("QMessageLogContext"); | ||
type Kind = cxx::kind::Trivial; | ||
} | ||
|
||
use crate::core::qtlogging::ffi::category; | ||
pub use ffi::{qt_message_output, QtMsgType}; |