Skip to content

Commit 582ce49

Browse files
authored
Merge pull request #94 from ratijas/refactor
2 parents 5d1f561 + dc245ed commit 582ce49

File tree

8 files changed

+592
-364
lines changed

8 files changed

+592
-364
lines changed

qmetaobject/qmetaobject_rust.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ struct RustObject : Base {
9898
struct RustObjectDescription {
9999
size_t size;
100100
const QMetaObject *baseMetaObject;
101-
QObject *(*create)(const TraitObject*, const TraitObject*);
102-
void (*qmlConstruct)(void*, const TraitObject*, const TraitObject*, void (*extra_destruct)(QObject *));
103-
TraitObject (*get_rust_refcell)(QObject*); // Possible optimisation: make this an offset
101+
QObject *(*create)(const TraitObject *, const TraitObject *);
102+
void (*qmlConstruct)(void *, const TraitObject *, const TraitObject *, void (*extra_destruct)(QObject *));
103+
TraitObject (*get_rust_refcell)(QObject *); // Possible optimisation: make this an offset
104104
};
105105

106106
template<typename T>
@@ -121,15 +121,13 @@ const RustObjectDescription *rustObjectDescription() {
121121
q->ptr_qobject = *self_ptr;
122122
q->extra_destruct = extra_destruct;
123123
},
124-
[](QObject *q) { return static_cast<T*>(q)->ptr_qobject; }
125-
124+
[](QObject *q) { return static_cast<T *>(q)->ptr_qobject; }
126125
};
127126
return &desc;
128127
}
129128

130129
using CreatorFunction = void (*)(void *);
131130

132-
133131
namespace QtPrivate {
134132
// Hack to access QMetaType::registerConverterFunction which is private, but ConverterFunctor
135133
// is a friend

qmetaobject/src/connections.rs

Lines changed: 82 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,58 @@ use std;
2020
use std::os::raw::c_void;
2121

2222
cpp! {{
23-
#include <QtCore/QObject>
24-
#include "qmetaobject_rust.hpp"
23+
#include <QtCore/QObject>
24+
#include "qmetaobject_rust.hpp"
2525

26-
// Access private function of QObject. Pretend to define QObjectPrivate.
27-
// This rely on QObjectPrivate being a friend of QObject.
28-
class QObjectPrivate {
26+
// Access private function of QObject. Pretend to define QObjectPrivate.
27+
// This rely on QObjectPrivate being a friend of QObject.
28+
class QObjectPrivate {
2929
public:
30-
static QMetaObject::Connection rust_connectImpl(const QObject *sender, void **signal,
31-
const QObject *receiver, void **slotPtr,
32-
QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type,
33-
const int *types, const QMetaObject *senderMetaObject) {
34-
return QObject::connectImpl(sender, signal, receiver, slotPtr, slot, type, types, senderMetaObject);
35-
}
36-
};
37-
38-
class RustSlotOject : public QtPrivate::QSlotObjectBase
39-
{
40-
TraitObject slot;
41-
static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) {
42-
switch (which) {
43-
case Destroy:
44-
delete static_cast<RustSlotOject*>(this_);
45-
break;
46-
case Call: {
47-
auto slot = static_cast<RustSlotOject*>(this_)->slot;
48-
rust!(RustSlotObject_call[slot : *mut dyn FnMut(*const *const c_void) as "TraitObject",
49-
a : *const *const c_void as "void**"] {
50-
unsafe { (*slot)(a); }
51-
});
52-
break;
30+
static QMetaObject::Connection rust_connectImpl(
31+
const QObject *sender,
32+
void **signal,
33+
const QObject *receiver,
34+
void **slotPtr,
35+
QtPrivate::QSlotObjectBase *slot,
36+
Qt::ConnectionType type,
37+
const int *types,
38+
const QMetaObject *senderMetaObject
39+
) {
40+
return QObject::connectImpl(sender, signal, receiver, slotPtr, slot,
41+
type, types, senderMetaObject);
5342
}
54-
case Compare: // not implemented
55-
case NumOperations:
56-
Q_UNUSED(ret); Q_UNUSED(r);
43+
};
44+
45+
class RustSlotOject : public QtPrivate::QSlotObjectBase
46+
{
47+
TraitObject slot;
48+
static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) {
49+
switch (which) {
50+
case Destroy:
51+
delete static_cast<RustSlotOject*>(this_);
52+
break;
53+
case Call: {
54+
auto slot = static_cast<RustSlotOject*>(this_)->slot;
55+
rust!(RustSlotObject_call[slot : *mut dyn FnMut(*const *const c_void) as "TraitObject",
56+
a : *const *const c_void as "void**"] {
57+
unsafe { (*slot)(a); }
58+
});
59+
break;
60+
}
61+
case Compare: // not implemented
62+
case NumOperations:
63+
Q_UNUSED(ret); Q_UNUSED(r);
64+
}
5765
}
58-
}
59-
public:
60-
explicit RustSlotOject(TraitObject slot) : QSlotObjectBase(&impl), slot(slot) {}
61-
~RustSlotOject() {
62-
rust!(RustSlotOject_destruct [slot : *mut dyn FnMut(*const *const c_void) as "TraitObject"] {
63-
let _ = unsafe { Box::from_raw(slot) };
64-
});
65-
}
66-
Q_DISABLE_COPY(RustSlotOject);
67-
};
66+
public:
67+
explicit RustSlotOject(TraitObject slot) : QSlotObjectBase(&impl), slot(slot) {}
68+
~RustSlotOject() {
69+
rust!(RustSlotOject_destruct [slot : *mut dyn FnMut(*const *const c_void) as "TraitObject"] {
70+
let _ = unsafe { Box::from_raw(slot) };
71+
});
72+
}
73+
Q_DISABLE_COPY(RustSlotOject);
74+
};
6875

6976

7077
}}
@@ -75,28 +82,31 @@ cpp_class!(
7582
/// Can be used to detect if a connection is valid, and to disconnect a connection.
7683
pub unsafe struct ConnectionHandle as "QMetaObject::Connection"
7784
);
85+
7886
impl ConnectionHandle {
7987
/// Disconnect this connection.
8088
///
8189
/// After this function is called, all ConnectionHandle referring to this connection will be invalided.
8290
/// Calling disconnect on an invalided connection does nothing.
8391
pub fn disconnect(&mut self) {
84-
unsafe { cpp!([self as "const QMetaObject::Connection*"] { QObject::disconnect(*self); }) }
92+
cpp!(unsafe [self as "const QMetaObject::Connection *"] {
93+
QObject::disconnect(*self);
94+
})
8595
}
8696

8797
/// Returns true if the connection is valid.
8898
pub fn is_valid(&self) -> bool {
89-
unsafe {
90-
cpp!([self as "const QMetaObject::Connection*"] -> bool as "bool" { return *self; })
91-
}
99+
cpp!(unsafe [self as "const QMetaObject::Connection *"] -> bool as "bool" {
100+
return *self; // implicit conversion
101+
})
92102
}
93103
}
94104

95105
cpp_class!(
96106
/// Internal class that can be used to construct C++ signal. Should only be used as an implementation
97-
/// details when writing bindings to Qt signals to construct a `CppSignal<...>`
107+
/// details when writing bindings to Qt signals to construct a `CppSignal<...>`.
98108
///
99-
/// It has the same size as a `void(QObject::*)()` and can be constructed from signals.
109+
/// It has the same size as a `void (QObject::*)()` and can be constructed from signals.
100110
pub unsafe struct SignalCppRepresentation as "SignalCppRepresentation"
101111
);
102112

@@ -108,16 +118,19 @@ pub struct CppSignal<Args> {
108118
inner: SignalCppRepresentation,
109119
phantom: std::marker::PhantomData<Args>,
110120
}
121+
111122
impl<Args> CppSignal<Args> {
112123
pub unsafe fn new(inner: SignalCppRepresentation) -> Self {
113124
CppSignal { inner, phantom: Default::default() }
114125
}
115126
}
127+
116128
impl<Args> Clone for CppSignal<Args> {
117129
fn clone(&self) -> Self {
118130
*self
119131
}
120132
}
133+
121134
impl<Args> Copy for CppSignal<Args> {}
122135

123136
/// Types of signals constructed with the qt_signal! macro.
@@ -129,11 +142,16 @@ pub struct RustSignal<Args> {
129142
phantom: std::marker::PhantomData<Args>,
130143
_u: bool, // Actually put a field so it has a size;
131144
}
145+
132146
impl<Args> Default for RustSignal<Args> {
133147
fn default() -> Self {
134-
RustSignal { phantom: Default::default(), _u: false }
148+
RustSignal {
149+
phantom: Default::default(),
150+
_u: Default::default()
151+
}
135152
}
136153
}
154+
137155
impl<Args> RustSignal<Args> {
138156
/// return a CppSignal corresponding to this signal.
139157
///
@@ -225,11 +243,20 @@ pub unsafe fn connect<Args, F: Slot<Args>>(
225243
let apply_closure = move |a: *const *const c_void| slot.apply(a);
226244
let b: Box<dyn FnMut(*const *const c_void)> = Box::new(apply_closure);
227245
let slot_raw = Box::into_raw(b);
228-
/*unsafe*/
229-
{
230-
cpp!([sender as "const QObject*", mut cpp_signal as "SignalCppRepresentation", slot_raw as "TraitObject"] -> ConnectionHandle as "QMetaObject::Connection" {
231-
return QObjectPrivate::rust_connectImpl(sender, reinterpret_cast<void **>(&cpp_signal), sender, nullptr,
232-
new RustSlotOject(slot_raw), Qt::DirectConnection, nullptr, sender->metaObject());
233-
})
234-
}
246+
cpp!(unsafe [
247+
sender as "const QObject *",
248+
mut cpp_signal as "SignalCppRepresentation",
249+
slot_raw as "TraitObject"
250+
] -> ConnectionHandle as "QMetaObject::Connection" {
251+
return QObjectPrivate::rust_connectImpl(
252+
sender,
253+
reinterpret_cast<void **>(&cpp_signal),
254+
sender,
255+
nullptr,
256+
new RustSlotOject(slot_raw),
257+
Qt::DirectConnection,
258+
nullptr,
259+
sender->metaObject()
260+
);
261+
})
235262
}

qmetaobject/src/future.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ cpp! {{
101101
/// Note that this function returns immediately. A Qt event loop need to be running
102102
/// on the current thread so the future can be executed. (It is Ok if the Qt event
103103
/// loop hasn't started yet when this function is called)
104-
pub fn execute_async(f: impl Future<Output = ()> + 'static) {
105-
let f = Box::into_raw(Box::new(f)) as *mut dyn Future<Output = ()>;
104+
pub fn execute_async(f: impl Future<Output=()> + 'static) {
105+
let f: *mut dyn Future<Output=()> = Box::into_raw(Box::new(f));
106106
unsafe {
107107
let waker = cpp!([f as "TraitObject"] -> *const() as "Waker*" {
108108
return new Waker(f);
@@ -112,7 +112,7 @@ pub fn execute_async(f: impl Future<Output = ()> + 'static) {
112112
}
113113

114114
// SAFETY: caller must ensure that given future hasn't returned Poll::Ready earlier.
115-
unsafe fn poll_with_qt_waker(waker: *const (), future: Pin<&mut dyn Future<Output = ()>>) -> bool {
115+
unsafe fn poll_with_qt_waker(waker: *const (), future: Pin<&mut dyn Future<Output=()>>) -> bool {
116116
cpp!([waker as "Waker*"] { waker->refs++; });
117117
let waker = std::task::RawWaker::new(waker, &QT_WAKER_VTABLE);
118118
let waker = std::task::Waker::from_raw(waker);
@@ -133,22 +133,26 @@ unsafe fn poll_with_qt_waker(waker: *const (), future: Pin<&mut dyn Future<Outpu
133133
pub unsafe fn wait_on_signal<Args: SignalArgArrayToTuple>(
134134
sender: *const c_void,
135135
signal: crate::connections::CppSignal<Args>,
136-
) -> impl Future<Output = <Args as SignalArgArrayToTuple>::Tuple> {
136+
) -> impl Future<Output=<Args as SignalArgArrayToTuple>::Tuple> {
137137
enum ConnectionFutureState<Args: SignalArgArrayToTuple> {
138138
Init { sender: *const c_void, signal: crate::connections::CppSignal<Args> },
139139
Started { handle: crate::connections::ConnectionHandle, waker: std::task::Waker },
140140
Finished { result: <Args as SignalArgArrayToTuple>::Tuple },
141141
Invalid,
142142
}
143+
143144
impl<Args: SignalArgArrayToTuple> std::marker::Unpin for ConnectionFutureState<Args> {}
145+
144146
struct ConnectionFuture<Args: SignalArgArrayToTuple>(ConnectionFutureState<Args>);
147+
145148
impl<Args: SignalArgArrayToTuple> Drop for ConnectionFuture<Args> {
146149
fn drop(&mut self) {
147150
if let ConnectionFutureState::Started { ref mut handle, .. } = &mut self.0 {
148151
handle.disconnect();
149152
}
150153
}
151154
}
155+
152156
impl<Args: SignalArgArrayToTuple> Future for ConnectionFuture<Args> {
153157
type Output = <Args as SignalArgArrayToTuple>::Tuple;
154158
fn poll(

0 commit comments

Comments
 (0)