grkek / iu

UI framework based on the Fusion/libui.cr library, with elements from watzon/cru.
MIT License
72 stars 5 forks source link

Crash when Area component callback accesses instance variable #3

Closed existXFx closed 1 month ago

existXFx commented 2 years ago

A class inherits Iu::Components::Area and implements on_* callback, will crash program when its instance access instance variables:

class MyArea < Iu::Components::Area
    def initialize(width = nil, height = width)
      @blah = "blah"
      super(width, height)
    end

    def on_draw(params : UI::AreaDrawParams)
       puts @blah
    end

    def on_mouse_event(mouse_event : UI::AreaMouseEvent);end
    def on_mouse_crossed(left : Bool);end
    def on_drag_broken;end
    def on_key_event(key_event : UI::AreaKeyEvent);end
end

I'm not familiar with Crystal. I think the reason is that the callback function passed to the libui C library forms a closure. The Iu shard wraps libui, a new member "data" is added to the AreaHandler structure to store pointers to an area objects. This allows libui to call back the on_* method implemented by the MyArea class, I'm not sure if this is the scenario described in Crystal document. After testing, this bug can be solved in this way:

@@on_mouse_event_cb = Proc(UI::AreaHandler*, UI::Area*, UI::AreaMouseEvent*, Nil).new { |h, a, e|
        # h.value.data.as(Area*).value.on_mouse_event(e.value).as(Nil)
        ::Box(Area).unbox(h.value.data).on_mouse_event(e.value).as(Nil)
}
# @handler.data = self.as(Void*)
@handler.data = ::Box.box(self)
grkek commented 2 years ago

Make a PR for it mate!

videotoaster commented 9 months ago

Went ahead and opened the PR, I applied this fix to each of the callbacks