hugopl / gi-crystal

Tool to generate Crystal bindings for gobject-based libraries (i.e. GTK)
BSD 3-Clause "New" or "Revised" License
45 stars 3 forks source link

Interface casts crashes #132

Closed hugopl closed 11 months ago

hugopl commented 11 months ago

Interface cast was implemented like normal object casts, but they aren't. However this way it works in some circustances.

In current test suit, expanding the C macros we get the GObject implementations:

static inline gboolean TEST_IS_IFACE (gpointer ptr) {
  return {
    GTypeInstance *__inst = (GTypeInstance*) (ptr);
    GType __t = (test_iface_get_type ());
    gboolean __r;
    if (!__inst)
      __r = (0);
    else if (__inst->g_class && __inst->g_class->g_type == __t)
      __r = (!(0));
    else
      __r = g_type_check_instance_is_a (__inst, __t);
    __r;
  };
}

static inline TestIfaceInterface * TEST_IFACE_GET_IFACE (gpointer ptr) {
  return (TestIfaceInterface*) g_type_interface_peek(((GTypeInstance*) ptr)->g_class, test_iface_get_type());
}

While in the bindings this is done as:

# Cast a `GObject::Object` to this type, returns nil if cast can't be made.
def self.cast?(obj : GObject::Object) : self?
  return if LibGObject.g_type_check_instance_is_a(obj, g_type).zero?

  instance = GICrystal.instance_pointer(obj)
  # This should never happen with GC resistant objects
  raise GICrystal::ObjectCollectedError.new if instance.null?

  instance.as(self)
end

i.e. we have only the instance cast implementation 😁