Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot implement vfunc Gtk::Widget#do_measure #32

Open
BlobCodes opened this issue Jun 17, 2022 · 5 comments
Open

Cannot implement vfunc Gtk::Widget#do_measure #32

BlobCodes opened this issue Jun 17, 2022 · 5 comments
Labels
bug Something isn't working vfunc Related to gobject virtual function implementation
Milestone

Comments

@BlobCodes
Copy link
Contributor

Trying to implement the vfunc measure results in a compile-time error:

Showing last frame. Use --error-trace for full trace.

There was a problem expanding macro '_register_do_measure'

Code in macro 'method_added'

 3 | _register_do_measure
     ^
Called macro defined in lib/libadwaita/lib/gi-crystal/src/auto/gtk-4.0/widget.cr:5053:13

 5053 | private macro _register_do_measure

Which expanded to:

 > 20 |         raise GICrystal::ObjectCollectedError.new if __temp_46 || __temp_47.null?
 > 21 | 
 > 22 |         __temp_47.as(self).do_measure(orientation, for_size, minimum, natural, minimum_baseline, natural_baseline)
                                                                     ^------
Error: undefined local variable or method 'minimum' for Mangaba::UI::Description.class

I think this is because the last four arguments are of type Int32* as four Int32 should be returned using pointers.

@hugopl hugopl added the bug Something isn't working label Jun 20, 2022
@hugopl
Copy link
Owner

hugopl commented Jun 22, 2022

out params aren't handled by ArgStrategy in Direction::CToCrystal mode yet, the code used by vfunc is the same made for signals, and there's no signals with out parameters.

We need to think how to "crystallize" this API, maybe letting measure return a tuple with these out parameters 🤔

The signature would be:
do_measure(orientation : Gtk::Orientation, for_size : Int32) : {Int32, Int32, Int32, Int32}

I would not like to expose pointers in the API

Or... we could let the signature return a NamedTuple:

do_measure(orientation : Gtk::Orientation, for_size : Int32) : {minimum: Int32, natural: Int32, minimum_baseline: Int32, natural_baseline: Int32}

The signature is longer and uglier, but less error prone to use in these cases of many out parameters.

There's also the alternative of mix between two... if there's just 2 out parameters, the return type is a tuple, starting from 3 parameters, a named tuple.

I tempted to choose that named tuple approach, despite of long to type it's safer... and BTW the user doesn't need to type the return type restriction in the method declaration.

@hugopl hugopl added this to the v0.14.0 milestone Jul 8, 2022
@BlobCodes
Copy link
Contributor Author

We need to think how to "crystallize" this API, maybe letting measure return a tuple with these out parameters

Often, it is allowed to set the pointers of the out parameters to NULL. In this case, the caller does not want a value. This is not really possible to communicate with Tuples. Maybe we can create an Out(T) type with only two methods #writable? and #value= that is just a pointer in disguise.

@hugopl
Copy link
Owner

hugopl commented Jul 31, 2022

The Out(T) approach is a bit Cish, however it's needed if the out parameter, if used, implies in some extra processing by the function.

Maybe we could do both approaches:

  • Bind it using a method with Out(T), for these uses cases where not setting some parameter matters.
    • The out parameters needed to be named arguments.
  • Bind it using a method that returns tuples/named tuples.
    • The internal implementation could be using the Out(T) version to make things simpler.

As their signature are different, they can have the same name, nowadays something similar is done when the method receives an array, there's a method that receives the array and another one that receives a variable number of arguments doing a splat.

I'm going to work on this soon, since it become a blocker for my app due to some Pango functions that return multiple items.

@hugopl hugopl modified the milestones: v0.14.0, v0.15.0 Sep 12, 2022
@hugopl hugopl modified the milestones: v0.15.0, v0.16.0 Feb 17, 2023
@hugopl
Copy link
Owner

hugopl commented May 3, 2023

I'm going to work on this soon, since it become a blocker for my app due to some Pango functions that return multiple items.

I need to never do any promises about what I'm going to fix/implement, since it depends on a combination of free time, mood and necessity, all 3 are not always present.

This is not really possible to communicate with Tuples.

It is, however you will need to write some nils, however I think for simplicity this will end up being implemented (some day) only as named tuples return values:

class FooWidget < Gtk::Widget
  @[GObject::Virtual]
  def measure(orientation, size)
    {minimum: 10,
     natural: 100,
     minimum_baseline: 10,
     natural_baseline: 10}
  end
end

@hugopl hugopl added the vfunc Related to gobject virtual function implementation label Jun 28, 2023
@hugopl
Copy link
Owner

hugopl commented Jul 20, 2023

I was implementing the measure virtual func in a project of mine, doing it manually to check how a proposed API for it would look like... and this NamedTuple idea looked not good at all. I'll follow with the GICrystal::Out type when implementing this in the future.

struct Out(T)
  @pointer : Pointer(T)

  delegate value=, to: @pointer
end

This Out type will be basically a wrapper to stdlib Pointer, what made me think if just throwing pointers in the vfunc API without this makeover would be enough, or at least simpler to implement in the generator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working vfunc Related to gobject virtual function implementation
Projects
None yet
Development

No branches or pull requests

2 participants