-
Notifications
You must be signed in to change notification settings - Fork 2
add generated action interface #10
Conversation
gio-subclass/src/action.rs
Outdated
iface_data: glib_ffi::gpointer | ||
) { | ||
callback_guard!(); | ||
let action_iface = &mut *(iface as *mut ffi::); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing the C interface struct type here after ffi::
gio-subclass/src/action.rs
Outdated
|
||
unsafe extern "C" fn action_get_type<T: ObjectType>( | ||
type_: glib_ffi::GType | ||
) -> glib::Type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is not needed for interfaces, what you basically have here is a trampoline calling a get_type
function on the interface... but there is none on GAction
gio-subclass/src/action.rs
Outdated
let interface_static = &*(ptr as *const T::InstanceStructType); | ||
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
imp.get_state_type() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like signal trampolines, this needs all the conversion stuff for the return value (from_glib_full
in this case) and also the parameters (none here). You also want to pass the &gio::Action
via &from_glib_borrow(ptr)
to this and all other functions
gio-subclass/src/action.rs
Outdated
let interface_static = &*(ptr as *const T::InstanceStructType); | ||
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
imp.change_state() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you want to pass both ptr
and value
to the function, which should work the same as in signal trampolines
gio-subclass/src/action.rs
Outdated
|
||
pub trait ActionImpl: AnyImpl + 'static { | ||
|
||
fn activate(&self, action: &T, parameter: Option<&glib::Variant>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The &T
here should be a &gio::Action
AFAIU
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I was thinking for a moment that we could make actionImpl generic over T? But i'm not sure if that has any benefits to it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That has the problem that you can't use Box<ActionImpl>
anymore but have to provide the type parameter everywhere, or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure. I can't even remember why I wanted to make it generic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not do that for now then :) It can always be dynamically casted if needed
Looks generally very good, the main thing missing here at this point seems to be the type conversion between C and Rust, which should be the same as in the signal trampolines |
Aside from missing imports and so on, the largest issue remains those trampolines. I've been looking at the signals implementation, but I can only find stuff marked as TODO :) |
There's https://github.com/gtk-rs/gir/blob/master/src/codegen/trampoline.rs, specifically the |
Thanks. I'm not sure how correct this is, but it seems like it could work |
gio-subclass/src/action.rs
Outdated
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
let wrap: T = from_glib_borrow(instance); | ||
imp.activate(&wrap, &from_glib_none(action), /*Unknown conversion*/parameter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be &from_glib_borrow(action)
(and IIRC would be for signals). Not sure why it falls apart on the GVariant
, in the function just below it works :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally this should do &from_glib_borrow
for all shared/boxed/object types (if transfer none
) like it would in signal trampolines. There's probably a code path that has to be enabled for your case too here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, all of the 'action' conversions here are incorrect. That's what 'wrap' is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! Indeed
gio-subclass/src/action.rs
Outdated
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
let wrap: T = from_glib_borrow(instance); | ||
imp.get_name(&wrap, &from_glib_none(action))/*Not checked*/.to_glib_none().0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value is unsafe but that's because the C API is broken, this needs a manual implementation.
You need to return a string here that is valid for the whole lifetime of the underlying action object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@federicomenaquintero things like this are btw examples why I think we will need an override system somewhere between gnome-class and the .gir files, and why I believe the trampolines and some glue infrastructure should live in the gtk/etc bindings for gnome-class to use.
I have some more examples in GStreamer :) We should talk about this at the next hackfest in more detail
gio-subclass/src/action.rs
Outdated
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
let wrap: T = from_glib_borrow(instance); | ||
imp.get_parameter_type(&wrap, &from_glib_none(action))/*Not checked*/.to_glib_none().0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as for the name
gio-subclass/src/action.rs
Outdated
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
let wrap: T = from_glib_borrow(instance); | ||
imp.get_state(&wrap, &from_glib_none(action)).to_glib_full() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This return value could use an optimization but not important right now
let ret = imp.get_state(...);
let ptr = ret.to_glib_none().0;
mem::forget(ret);
ptr
gio-subclass/src/action.rs
Outdated
let imp = instance.get_impl(); | ||
let imp = (*(*interface_static).imp_static).get_impl(imp); | ||
let wrap: T = from_glib_borrow(instance); | ||
imp.get_state_type(&wrap, &from_glib_none(action))/*Not checked*/.to_glib_none().0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same problem as for name
As far as the gir is concerned, I don't think I can manage to fix the c-api broken-ness. So either I fix that manually, or we come up with a plan to pull implementations from a separate file. |
Generally I was thinking separate files should work fine, e.g. marking a vfunc as ignore in the toml file and then having one file per vfunc that defines the 3 parts of it: 1) the trait function signature, 2) the chaining up part, 3) the trampoline. And then during code generation, those parts are spliced into the output. |
Do you have any proposition regarding the syntax of that file? I'd like to make it as simple as possible to know what content to splice where. Ideally, the gir should not know about what's in that file, only which block to insert where. |
Yes I agree, ideally we wouldn't need to parse it at all. So maybe just separate files with the actual content that is inserted in the relevant places? |
Something like this? (see gir for implementatin details) |
Yes, exactly that :) |
diff --git a/gio-subclass/src/action.rs b/gio-subclass/src/action.rs
index 7542553..9a6a927 100644
--- a/gio-subclass/src/action.rs
+++ b/gio-subclass/src/action.rs
@@ -78,9 +78,9 @@ unsafe extern "C" fn action_activate<T: ObjectType>
let param = if parameter.is_null(){
None
}else{
- Some(&from_glib_none(parameter))
+ Some(from_glib_none(parameter))
};
- imp.activate(&wrap, param)
+ imp.activate(&wrap, param.as_ref())
}
unsafe extern "C" fn action_change_state<T: ObjectType>
@@ -206,7 +206,7 @@ unsafe extern "C" fn action_init<T: ObjectType>(
iface_data: glib_ffi::gpointer
) {
callback_guard!();
- let action_iface = &mut *(iface as *mut gio_ffi::GAction);
+ let action_iface = &mut *(iface as *mut gio_ffi::GActionInterface);
let iface_type = (*(iface as *const gobject_ffi::GTypeInterface)).g_type;
let type_ = (*(iface as *const gobject_ffi::GTypeInterface)).g_instance_type;
let klass = &mut *(gobject_ffi::g_type_class_ref(type_) as *mut ClassStruct<T>); This is required to make it compile. Wrong type is used for the interface, and some lifetime issues with a variable |
Thanks! |
So while this thing now compiles, I have no idea how to use it. I'd guess we need |
No, |
You can find an example that compiles here. Let me know if you have any questions about the code, and also note the function I've added to |
Were you able to write a subclass of |
No. Not yet. I don't know what to do with that one either :) |
Ah, I thought you started with |
This still panics when using the getter on a Boxed VariantType though
I've regenerated one last time. It now includes some |
Ok, go for it then :) |
Ready for merge? |
Yes, but please don't forget to look at the property flag stuff afterwards :) |
I'll do that soon. I'll need it anyway. |
Let's start off with the action interface, since that one is used by application at some point.
This generated file is not at all usable yet, but let's see where we get from here.