Re: Cannot `dynamic_cast` custom wrapped widget from Gtk::Builder



Ok, I think I figured it out the m4 include path issue for gmmproc, but I still can't load the widget from GtkBuilder even when using `_CLASS_GTKOBJECT`. I think that with two `-I` in the command line, one must be overriding the other. The following command line seems to work, and generates a reasonable .h file. 

~~~
M4PATH=/usr/lib/x86_64-linux-gnu/glibmm-2.4/proc/m4:/usr/lib/x86_64-linux-gnu/atkmm-1.6/proc/m4:/usr/lib/x86_64-linux-gnu/pangomm-1.4/proc/m4 /usr/lib/x86_64-linux-gnu/glibmm-2.4/proc/gmmproc -I /usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4 panzoomarea mm mm
~~~

When I diff the result between `_GOBJECT` and `_GTKOBJECT` the difference is pretty small, and I don't actually see anything meaningful that might affect Gtk::Builder. Also, I continue to get:

~~~
CRITICAL **: 11:07:27.571: Gtk::Builder::get_widget(): dynamic_cast<> failed.
~~~

when I try to retrieve the widget from a glade file. Here is the diff between the generated code with `_GOBJECT` and `_GTKOBJECT`:

~~~
diff --git a/tangent/gtkutil/mm/panzoomarea.cc b/tangent/gtkutil/mm/panzoomarea.cc
index 54b2477..5cc1913 100644
--- a/tangent/gtkutil/mm/panzoomarea.cc
+++ b/tangent/gtkutil/mm/panzoomarea.cc
@@ -159,10 +159,9 @@ static const Glib::SignalProxyInfo PanZoomArea_signal_area_draw_info = {
 
 namespace Glib {
 
-Glib::RefPtr<Gtk::PanZoomArea> wrap(GtkPanZoomArea* object, bool take_copy) {
-  return Glib::RefPtr<Gtk::PanZoomArea>(dynamic_cast<Gtk::PanZoomArea*>(
-      Glib::wrap_auto((GObject*)(object), take_copy)));
-  // We use dynamic_cast<> in case of multiple inheritance.
+Gtk::PanZoomArea* wrap(GtkPanZoomArea* object, bool take_copy) {
+  return dynamic_cast<Gtk::PanZoomArea*>(
+      Glib::wrap_auto((GObject*)(object), take_copy));
 }
 
 } /* namespace Glib */
@@ -312,17 +311,12 @@ gboolean PanZoomArea_Class::area_draw_callback(GtkPanZoomArea* self,
   return RType();
 }
 
-Glib::ObjectBase* PanZoomArea_Class::wrap_new(GObject* object) {
-  return new PanZoomArea((GtkPanZoomArea*)object);
+Glib::ObjectBase* PanZoomArea_Class::wrap_new(GObject* o) {
+  return manage(new PanZoomArea((GtkPanZoomArea*)(o)));
 }
 
 /* The implementation: */
 
-GtkPanZoomArea* PanZoomArea::gobj_copy() {
-  reference();
-  return gobj();
-}
-
 PanZoomArea::PanZoomArea(const Glib::ConstructParams& construct_params)
     : Gtk::DrawingArea(construct_params) {}
 
@@ -337,7 +331,9 @@ PanZoomArea& PanZoomArea::operator=(PanZoomArea&& src) noexcept {
   return *this;
 }
 
-PanZoomArea::~PanZoomArea() noexcept {}
+PanZoomArea::~PanZoomArea() noexcept {
+  destroy_();
+}
 
 PanZoomArea::CppClassType
     PanZoomArea::panzoomarea_class_;  // initialize static member
diff --git a/tangent/gtkutil/mm/panzoomarea.h b/tangent/gtkutil/mm/panzoomarea.h
index 2a3efd8..ac11ab5 100644
--- a/tangent/gtkutil/mm/panzoomarea.h
+++ b/tangent/gtkutil/mm/panzoomarea.h
@@ -24,18 +24,25 @@ class PanZoomArea_Class;
 namespace Gtk {
 
 class PanZoomArea : public Gtk::DrawingArea {
+ public:
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
+  typedef PanZoomArea CppObjectType;
+  typedef PanZoomArea_Class CppClassType;
+  typedef GtkPanZoomArea BaseObjectType;
+  typedef GtkPanZoomAreaClass BaseClassType;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
- public:
-  using CppObjectType = PanZoomArea;
-  using CppClassType = PanZoomArea_Class;
-  using BaseObjectType = GtkPanZoomArea;
-  using BaseClassType = GtkPanZoomAreaClass;
+  PanZoomArea(PanZoomArea&& src) noexcept;
+  PanZoomArea& operator=(PanZoomArea&& src) noexcept;
 
   // noncopyable
   PanZoomArea(const PanZoomArea&) = delete;
   PanZoomArea& operator=(const PanZoomArea&) = delete;
 
+  ~PanZoomArea() noexcept override;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
  private:
   friend class PanZoomArea_Class;
   static CppClassType panzoomarea_class_;
@@ -47,11 +54,6 @@ class PanZoomArea : public Gtk::DrawingArea {
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
  public:
-  PanZoomArea(PanZoomArea&& src) noexcept;
-  PanZoomArea& operator=(PanZoomArea&& src) noexcept;
-
-  ~PanZoomArea() noexcept override;
-
   /** Get the GType for this class, for use with the underlying GObject type
    * system.
    */
@@ -62,19 +64,29 @@ class PanZoomArea : public Gtk::DrawingArea {
   static GType get_base_type() G_GNUC_CONST;
 #endif
 
-  /// Provides access to the underlying C GObject.
+  /// Provides access to the underlying C GtkObject.
   GtkPanZoomArea* gobj() {
     return reinterpret_cast<GtkPanZoomArea*>(gobject_);
   }
 
-  /// Provides access to the underlying C GObject.
+  /// Provides access to the underlying C GtkObject.
   const GtkPanZoomArea* gobj() const {
     return reinterpret_cast<GtkPanZoomArea*>(gobject_);
   }
 
-  /// Provides access to the underlying C instance. The caller is responsible
-  /// for unrefing it. Use when directly setting fields in structs.
-  GtkPanZoomArea* gobj_copy();
+ public:
+  // C++ methods used to invoke GTK+ virtual functions:
+
+ protected:
+  // GTK+ Virtual Functions (override these to change behaviour):
+
+  // Default Signal Handlers::
+  /// This is a default handler for the signal signal_area_motion().
+  virtual bool on_area_motion(GdkEventMotion* event);
+  /// This is a default handler for the signal signal_area_button().
+  virtual bool on_area_button(GdkEventButton* event);
+  /// This is a default handler for the signal signal_area_draw().
+  virtual bool on_area_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr);
 
  private:
  public:
@@ -267,21 +279,6 @@ class PanZoomArea : public Gtk::DrawingArea {
    */
   Glib::PropertyProxy_ReadOnly<bool> property_demo_draw_enabled() const;
   ;
-
- public:
- public:
-  // C++ methods used to invoke GTK+ virtual functions:
-
- protected:
-  // GTK+ Virtual Functions (override these to change behaviour):
-
-  // Default Signal Handlers::
-  /// This is a default handler for the signal signal_area_motion().
-  virtual bool on_area_motion(GdkEventMotion* event);
-  /// This is a default handler for the signal signal_area_button().
-  virtual bool on_area_button(GdkEventButton* event);
-  /// This is a default handler for the signal signal_area_draw().
-  virtual bool on_area_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr);
 };
 
 }  // namespace Gtk
@@ -296,8 +293,7 @@ namespace Glib {
  *
  * @relates Gtk::PanZoomArea
  */
-Glib::RefPtr<Gtk::PanZoomArea> wrap(GtkPanZoomArea* object,
-                                    bool take_copy = false);
+Gtk::PanZoomArea* wrap(GtkPanZoomArea* object, bool take_copy = false);
 }  // namespace Glib
 
 #endif /* _TANGENT_GTKUTIL_MM_PANZOOMAREA_H */
~~~

On Sun, May 3, 2020 at 10:43 AM Josh Bialkowski <josh bialkowski gmail com> wrote:
> I suppose also panzoomarea.cc
Actually the .cc is less empty, but I think still broken. It contains 189 lines, compared to 575 lines when using _CLASS_GOBJECT. An example of some content it contains:

~~~
static gboolean __CPPNAME___signal_area_motion_callback(__CNAME__* self, GdkEventMotion* p0,void* data)
{
  using namespace Gtk;
  using SlotType = sigc::slot< bool,GdkEventMotion* >;

  auto obj = dynamic_cast<__CPPNAME__*>(Glib::ObjectBase::_get_current_wrapper((GObject*) self));
  // Do not try to call a signal on a disassociated wrapper.
  if(obj)
  {
    try
    {
      if(const auto slot = Glib::SignalProxyNormal::data_to_slot(data))
        return static_cast<int>((*static_cast<SlotType*>(slot))(p0));
    }
    catch(...)
    {
       Glib::exception_handlers_invoke();
    }
  }

  using RType = gboolean;
  return RType();
}

~~~
One difference I notice between the two is that `__CPPNAME__` is apparently not filled in. Again, I'm happy to paste/attach the full output if that would be useful. 

> Don't you get any kind of warning or error message?
Unfortunately I do not get any error message, so I'm at a loss for how to debug on my own :/. 

> Probably your gmmproc-command can be made much shorter:
If I leave off the M4PATH environment variable I get the following errors (for example, using the command line you suggested):

~~~
m4:/usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4/convert_gtk.m4:142: cannot open `convert_atk.m4': No such file or directory
m4:/usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4/convert_gtk.m4:143: cannot open `convert_pango.m4': No such file or directory
m4:/usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4/convert_gtkmm.m4:26: cannot open `convert_atk.m4': No such file or directory
m4:/usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4/convert_gtkmm.m4:29: cannot open `convert_pango.m4': No such file or directory
m4 failed with exit code 1.  Aborting...

~~~

I tried a few combinations of `M4PATH` and `-I`. Looking at the source for `gmmproc` I figured they would be equivalent, but that does not seem to be the case. When I *DO* include the M4PATH environment variable, the command succeeds with exit status zero and the only output I see on stdout is: 
~~~
gmmproc, panzoomarea: Unwrapped functions:
gmmproc:   gtk_panzoom_area_get_offset
gmmproc:   gtk_panzoom_area_set_offset

~~~

> You can add a --debug argument to the gmmproc command. 

Interesting. I gave that I try and I find `gtkmmproc_9536.g1` and `gtkmmproc_9536.g2` in `/tmp`. I'd be happy to paste the full content here but as a first attempt I'll try to point out just the relevant bits. In particular, `.g1` contains the following at the top of the file:

~~~
include(base.m4)dnl
_START(panzoomarea,tangent/gtkutil/mm,tangent_gtkutil_mm,2.56.0)dnl
//` clang-format off'

_PINCLUDE(gtkmm/private/drawingarea_p.h)
_PINCLUDE(tangent/gtkutil/mm/private/hack.h)
//` clang-format on'

#include <glibmm.h>
#include <gtkmm/drawingarea.h>

_SECTION(SECTION_HEADER2)
_NAMESPACE(Gtk)namespace Gtk {

_CLASS_START()class PanZoomArea : public Gtk::DrawingArea {
  _CLASS_GTKOBJECT(PanZoomArea, GtkPanZoomArea, GTK_PANZOOM_AREA,
                   Gtk::DrawingArea, GtkDrawingArea)

 public:
  _CTOR_DEFAULT

 public:
  //` _WRAP_METHOD(void get_offset(double offset[2]), gtk_panzoom_area_set_offset);'
  //` _WRAP_METHOD(void get_offset(double offset[2]), gtk_panzoom_area_set_offset);'
...
~~~

Which seems pretty reasonable... Looks like some things where added. But then `.g2` contains: 

~~~
#S 0
// Generated by gmmproc 2.56.0 -- DO NOT MODIFY!
#ifndef _TANGENT_GTKUTIL_MM_PANZOOMAREA_H
#define _TANGENT_GTKUTIL_MM_PANZOOMAREA_H





#include <glibmm/ustring.h>
#include <sigc++/sigc++.h>

// clang-format off



// clang-format on

#include <glibmm.h>
#include <gtkmm/drawingarea.h>

namespace Gtk {





#endif /* _TANGENT_GTKUTIL_MM_PANZOOMAREA_H */

#S 1
// Generated by gmmproc 2.56.0 -- DO NOT MODIFY!
#ifndef _TANGENT_GTKUTIL_MM_PANZOOMAREA_P_H
#define _TANGENT_GTKUTIL_MM_PANZOOMAREA_P_H


#include <gtkmm/private/drawingarea_p.h>
#include <tangent/gtkutil/mm/private/hack.h>


#endif /* _TANGENT_GTKUTIL_MM_PANZOOMAREA_P_H */

#S 2
// Generated by gmmproc 2.56.0 -- DO NOT MODIFY!
...
~~~

So it looks like things disappear somewhere between .g1 and .g2. 


On Sun, May 3, 2020 at 6:24 AM Kjell Ahlstedt <kjellahlstedt gmail com> wrote:

I don't understand why panzoomarea.h (and I suppose also panzoomarea.cc) is broken. Don't you get any kind of warning or error message? Probably your gmmproc-command can be made much shorter:

/usr/lib/x86_64-linux-gnu/glibmm-2.4/proc/gmmproc -I /usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4 panzoomarea mm mm

But I don't expect that to make a difference.

You can add a --debug argument to the gmmproc command. Some temporary files are then saved. You will probably find them in the /tmp directory.

Kjell

On 2020-05-03 02:07, Josh Bialkowski wrote:
Thanks Kjell, you have a good eye. I tried making the change to `_CLASS_GTKOBJECT` but I'm not sure what else needs to change. On my system `class_gtkobject.m4` is installed at `/usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4`, so I tried the following execution of gmmproc but the generated .h file is mostly empty:
~~~
M4PATH=/usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4:/usr/lib/x86_64-linux-gnu/glibmm-2.4/proc/m4 /usr/lib/x86_64-linux-gnu/glibmm-2.4/proc/gmmproc -I /usr/lib/x86_64-linux-gnu/glibmm-2.4/proc/m4 -I /usr/lib/x86_64-linux-gnu/gtkmm-3.0/proc/m4 panzoomarea mm mm
~~~

The generated `panzoomarea.h` looks broken:
~~~
// Generated by gmmproc 2.56.0 -- DO NOT MODIFY!
#ifndef _TANGENT_GTKUTIL_MM_PANZOOMAREA_H
#define _TANGENT_GTKUTIL_MM_PANZOOMAREA_H


#include <glibmm/ustring.h>
#include <sigc++/sigc++.h>

// clang-format off


// clang-format on

#include <glibmm.h>
#include <gtkmm/drawingarea.h>

namespace Gtk {


#endif /* _TANGENT_GTKUTIL_MM_PANZOOMAREA_H */

~~~

here is the full `panzoomarea.hg`:
~~~
// clang-format off
_DEFS(tangent/gtkutil/mm, tangent)
_PINCLUDE(gtkmm/private/drawingarea_p.h)
_PINCLUDE(tangent/gtkutil/mm/private/hack.h)
// clang-format on

#include <glibmm.h>
#include <gtkmm/drawingarea.h>

namespace Gtk {

class PanZoomArea : public Gtk::DrawingArea {
  _CLASS_GTKOBJECT(PanZoomArea, GtkPanZoomArea, GTK_PANZOOM_AREA,
                   Gtk::DrawingArea, GtkDrawingArea)

 public:
  _CTOR_DEFAULT

 public:
  // _WRAP_METHOD(void get_offset(double offset[2]), gtk_panzoom_area_set_offset);
  // _WRAP_METHOD(void get_offset(double offset[2]), gtk_panzoom_area_set_offset);

  _WRAP_METHOD(double get_scale(), gtk_panzoom_area_get_scale);
  _WRAP_METHOD(void set_scale(double scale), gtk_panzoom_area_set_scale);
  _WRAP_METHOD(double get_scale_rate(), gtk_panzoom_area_get_scale_rate);
  _WRAP_METHOD(void set_scale_rate(double rate),
               gtk_panzoom_area_set_scale_rate);

  // TODO(josh): can't wrap a signal whose default handler has a different
  // name than the name of the signal.
  _WRAP_SIGNAL(bool area_motion(GdkEventMotion* event), "area-motion");
  _WRAP_SIGNAL(bool area_button(GdkEventButton* event), "area-button");

// clang-format off
#m4 _CONVERSION(`CairoContext*',`const ::Cairo::RefPtr< ::Cairo::Context>&',`::Cairo::RefPtr< ::Cairo::Context>(new ::Cairo::Context($3, false /* has_reference */))')
#m4 _CONVERSION(`const ::Cairo::RefPtr< ::Cairo::Context>&',`CairoContext*',`($3)->cobj()')
  _WRAP_SIGNAL(bool area_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr),
               "area-draw");
  // clang-format on

  _WRAP_PROPERTY("offset-x-adjustment", Glib::RefPtr<Gtk::Adjustment>);
  _WRAP_PROPERTY("offset-y-adjustment", Glib::RefPtr<Gtk::Adjustment>);
  _WRAP_PROPERTY("scale-adjustment", Glib::RefPtr<Gtk::Adjustment>);
  _WRAP_PROPERTY("scale-rate-adjustment", Glib::RefPtr<Gtk::Adjustment>);
  _WRAP_PROPERTY("active", bool);
  _WRAP_PROPERTY("pan-button", int);
  _WRAP_PROPERTY("demo-draw-enabled", bool);
};

}  // namespace Gtk

~~~

Is there something else I need to make the `_CLASS_GTKOBJECT` macro work?

Thanks for the help,
Josh




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]