gtk-rs / gir

Tool to generate rust bindings and user API for glib-based libraries
https://gtk-rs.org/gir/book/
MIT License
229 stars 101 forks source link

What to do about private copy and free functions? #279

Open antoyo opened 7 years ago

antoyo commented 7 years ago

Hello. I found a type in webkit2gtk which has private copy and free functions. How can I create a boxed type glib wrapper for this type if these functions are private? By the way, I don't think this object will be freed by the user code. Thanks.

EPashkin commented 7 years ago

Sees you need implement all of it manually (like in https://github.com/gtk-rs/glib/blob/master/src/boxed.rs). You need at minimum implement glib::translate::FromGlibPtr<*mut WebKitScriptDialog> and ToGlibPtrMut for it. As example dialogs functions you can temporary add copy and free for <record name="ScriptDialog" to WebKit2-4.0.gir (I copied it from GtkTreePath) and generate.

      <method name="copy" c:identifier="webkit_script_dialog_copy">
        <doc xml:space="preserve">Creates a new #GtkTreePath-struct as a copy of @path.</doc>
        <return-value transfer-ownership="full">
          <doc xml:space="preserve">a new #GtkTreePath-struct</doc>
          <type name="ScriptDialog" c:type="WebKitScriptDialog*"/>
        </return-value>
        <parameters>
          <instance-parameter name="path" transfer-ownership="none">
            <doc xml:space="preserve">a #GtkTreePath-struct</doc>
            <type name="ScriptDialog" c:type="const WebKitScriptDialog*"/>
          </instance-parameter>
        </parameters>
      </method>
      <method name="free" c:identifier="webkit_script_dialog_free">
        <doc xml:space="preserve">Frees @path. If @path is %NULL, it simply returns.</doc>
        <return-value transfer-ownership="none">
          <type name="none" c:type="void"/>
        </return-value>
        <parameters>
          <instance-parameter name="path"
                              transfer-ownership="none"
                              nullable="1"
                              allow-none="1">
            <doc xml:space="preserve">a #GtkTreePath-struct</doc>
            <type name="ScriptDialog" c:type="WebKitScriptDialog*"/>
          </instance-parameter>
        </parameters>
      </method>
gkoz commented 7 years ago

@antoyo This is a confusing situation. free being private implies to me you can't own it. I haven't found any functions returning WebKitScriptDialog*. We might need more context here.

EPashkin commented 7 years ago

@gkoz It only used as trampoline parameter: https://github.com/antoyo/webkit2gtk-rs/blob/master/src/auto/web_view.rs#L722-L726

antoyo commented 7 years ago

Perhaps this code is wrong? I remember I had some issues and that way was the only working code that I found.

gkoz commented 7 years ago

I guess the correct (as correct as possible under current circumstances) trampoline code would be

unsafe extern "C" fn script_dialog_trampoline(this: *mut ffi::WebKitWebView, dialog: *mut ffi::WebKitScriptDialog, f: glib_ffi::gpointer) -> glib_ffi::gboolean {
    callback_guard!();
    let f: &Box_<Fn(&WebView, &mut ScriptDialog) -> bool + 'static> = transmute(f);
    let mut dialog = FromGlibPtr::from_glib_borrow(dialog);
    let ret = f(&from_glib_none(this), &mut dialog).to_glib();
    mem::forget(dialog);
    ret
}

When implementing ScriptDialog you give panicing functions to the macro to catch misuses:

glib_wrapper! {
    pub struct ScriptDialog(Boxed<ffi::WebKitScriptDialog>);

    match fn {
        copy => |ptr| nope(ptr),
        free => |ptr| nope(ptr),
    }
}

unsafe fn nope(ptr: *mut ffi::WebKitScriptDialog) -> *mut ffi::WebKitScriptDialog {
    panic!()
}