Hi!
I'm playing with Rust and I'm trying to write prototype Rust bindings for wlroots, a Wayland compositor library.
wlroots makes extensive use of intrusive linked lists (they are similar to the kernel's). That means I need to use Pin
to ensure the pointers aren't moved around by Rust.
My current WIP code is here: ~emersion/wlroots-rs: wlroots-sys/examples/basic.rs - sourcehut git
I'm currently trying to generalize the logic a bit in this branch: ~emersion/wlroots-rs: wlroots-sys/examples/basic.rs - sourcehut git
However I'm hitting this error:
error[E0401]: can't use generic parameters from outer function
--> examples/basic.rs:137:21
|
126 | impl<D> Backend<D> where D: BackendHandler {
| - type parameter from outer function
127 | pub fn autocreate(display: &Display<D>) -> Result<Pin<Box<Backend<D>>>, ()> {
| ---------- try adding a local generic parameter in this method instead
...
137 | Backend<D>,
| ^ use of generic parameter from outer function
Any ideas how to fix that? I can't wrap my head around this error. Maybe I need to change how my offset_of!
macro works?
Simon
alice
September 6, 2022, 12:51pm
2
The handle
fn would need to be generic itself for this to work.
I note that you don't necessarily need Pin
. Storing a raw pointer to the allocation will work just as well as a Pin<Box<...>>
, and may fit better together with the C API you're trying to talk to.
1 Like
Hm, I've tried doing this, but it doesn't work…
diff --git a/wlroots-sys/examples/basic.rs b/wlroots-sys/examples/basic.rs
index 6b691fba2b86..ee85789721b4 100644
--- a/wlroots-sys/examples/basic.rs
+++ b/wlroots-sys/examples/basic.rs
@@ -78,9 +78,13 @@ impl Listener {
macro_rules! init_listener {
($ptr:expr, $container:ty, $field:ident, $signal:expr, $handler:ident) => {{
- extern "C" fn handle(l: *mut wl_listener, _: *mut c_void) {
+ trait Handler {
+ fn $handler(&mut self);
+ }
+
+ extern "C" fn handle<T>(l: *mut wl_listener, _: *mut c_void) where T: Handler {
let ptr = unsafe {
- let ptr = container_of!(l, $container, $field.listener) as *mut $container;
+ let ptr = container_of!(l, T, $field.listener) as *mut T;
ptr.as_mut().unwrap()
};
ptr.$handler();
@@ -90,7 +94,7 @@ macro_rules! init_listener {
let l = $ptr
.as_mut()
.map_unchecked_mut(|container| &mut container.$field);
- l.init($signal, handle);
+ l.init($signal, handle::<$container>);
}
}};
}
error[E0277]: the trait bound `Backend<D>: Handler` is not satisfied
--> examples/basic.rs:97:29
|
97 | l.init($signal, handle::<$container>);
| ^^^^^^^^^^^^^^^^^^^^ the trait `Handler` is not implemented for `Backend<D>`
...
139 | / init_listener!(
140 | | backend,
141 | | Backend<D>,
142 | | destroy,
143 | | &mut ptr.events.destroy,
144 | | handle_destroy
145 | | );
| |_________- in this macro invocation
|
note: required by a bound in `handle`
--> examples/basic.rs:85:79
|
85 | extern "C" fn handle<T>(l: *mut wl_listener, _: *mut c_void) where T: Handler {
| ^^^^^^^ required by this bound in `handle`
...
139 | / init_listener!(
140 | | backend,
141 | | Backend<D>,
142 | | destroy,
143 | | &mut ptr.events.destroy,
144 | | handle_destroy
145 | | );
| |_________- in this macro invocation
= note: this error originates in the macro `init_listener` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0609]: no field `destroy` on type `T`
--> examples/basic.rs:142:13
|
85 | extern "C" fn handle<T>(l: *mut wl_listener, _: *mut c_void) where T: Handler {
| - type parameter 'T' declared here
...
142 | destroy,
| ^^^^^^^
alice
September 8, 2022, 6:39am
4
It definitely did work! Your new error is completely unrelated, and the error you asked about was solved.
1 Like
… This solution replaces an error with another error. I am not sure it's the correct way forward. Any idea how to fix it?
alice
September 10, 2022, 7:55am
6
I don't know why you get the error you get, since I can't see the full code. Maybe you can post a playground with the full code?
The full code is in the Git repo. Branch handler
, as linked above.
I think I've managed to get to the next step (now hitting yet another error with RefCell
), but it's not looking pretty at all.
diff --git a/wlroots-sys/examples/basic.rs b/wlroots-sys/examples/basic.rs
index 6b691fba2b86..406ae0a65e9e 100644
--- a/wlroots-sys/examples/basic.rs
+++ b/wlroots-sys/examples/basic.rs
@@ -77,10 +77,12 @@ impl Listener {
}
macro_rules! init_listener {
- ($ptr:expr, $container:ty, $field:ident, $signal:expr, $handler:ident) => {{
- extern "C" fn handle(l: *mut wl_listener, _: *mut c_void) {
+ ($ptr:expr, $container:ident, $field:ident, $signal:expr, $handler:ident) => {{
+ // TODO: add BackendHandler and D as macro params
+
+ extern "C" fn handle<H>(l: *mut wl_listener, _: *mut c_void) where H: BackendHandler {
let ptr = unsafe {
- let ptr = container_of!(l, $container, $field.listener) as *mut $container;
+ let ptr = container_of!(l, $container<H>, $field.listener) as *mut $container<H>;
ptr.as_mut().unwrap()
};
ptr.$handler();
@@ -90,7 +92,7 @@ macro_rules! init_listener {
let l = $ptr
.as_mut()
.map_unchecked_mut(|container| &mut container.$field);
- l.init($signal, handle);
+ l.init($signal, handle::<D>);
}
}};
}
@@ -134,7 +136,7 @@ impl<D> Backend<D> where D: BackendHandler {
});
init_listener!(
backend,
- Backend<D>,
+ Backend,
destroy,
&mut ptr.events.destroy,
handle_destroy
system
Closed
December 9, 2022, 8:11am
9
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.