CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867

    Trying to get my head around GTK+ casting

    GTK+ contains a widget known as a FileChooserButton. When pressed, it launches a dialog box allowing the user to select a file. After the dialog box closes, the chosen file's name appears in the button and the programmer can obtain a path to the chosen file using gtk_file_chooser_get_filename(). This requires a pointer to GtkFileChooser. Note that GtkFileChooser is not the same thing as GtkFileChooserButton. GtkFileChooser is essentially a collection of helper functions for dealing with the chosen file. Here's the header file for the button:-

    Code:
    #if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
    #error "Only <gtk/gtk.h> can be included directly."
    #endif
    
    #ifndef __GTK_FILE_CHOOSER_BUTTON_H__
    #define __GTK_FILE_CHOOSER_BUTTON_H__
    
    #include <gtk/gtkhbox.h>
    #include <gtk/gtkfilechooser.h>
    
    G_BEGIN_DECLS
    
    #define GTK_TYPE_FILE_CHOOSER_BUTTON            (gtk_file_chooser_button_get_type ())
    #define GTK_FILE_CHOOSER_BUTTON(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER_BUTTON, GtkFileChooserButton))
    #define GTK_FILE_CHOOSER_BUTTON_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_BUTTON, GtkFileChooserButtonClass))
    #define GTK_IS_FILE_CHOOSER_BUTTON(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_CHOOSER_BUTTON))
    #define GTK_IS_FILE_CHOOSER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_CHOOSER_BUTTON))
    #define GTK_FILE_CHOOSER_BUTTON_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_BUTTON, GtkFileChooserButtonClass))
    
    typedef struct _GtkFileChooserButton        GtkFileChooserButton;
    typedef struct _GtkFileChooserButtonPrivate GtkFileChooserButtonPrivate;
    typedef struct _GtkFileChooserButtonClass   GtkFileChooserButtonClass;
    
    struct _GtkFileChooserButton
    {
      /*< private >*/
      GtkHBox parent;
    
      GtkFileChooserButtonPrivate *GSEAL (priv);
    };
    
    struct _GtkFileChooserButtonClass
    {
      /*< private >*/
      GtkHBoxClass parent_class;
    
      void (* file_set) (GtkFileChooserButton *fc);
    
      void (*__gtk_reserved1);
      void (*__gtk_reserved2);
      void (*__gtk_reserved3);
      void (*__gtk_reserved4);
      void (*__gtk_reserved5);
      void (*__gtk_reserved6);
      void (*__gtk_reserved7);
    };
    
    
    GType                 gtk_file_chooser_button_get_type         (void) G_GNUC_CONST;
    GtkWidget *           gtk_file_chooser_button_new              (const gchar          *title,
    								GtkFileChooserAction  action);
    
    #ifndef GTK_DISABLE_DEPRECATED
    GtkWidget *           gtk_file_chooser_button_new_with_backend (const gchar          *title,
    								GtkFileChooserAction  action,
    								const gchar          *backend);
    #endif /* GTK_DISABLE_DEPRECATED */
    
    GtkWidget *           gtk_file_chooser_button_new_with_dialog  (GtkWidget            *dialog);
    G_CONST_RETURN gchar *gtk_file_chooser_button_get_title        (GtkFileChooserButton *button);
    void                  gtk_file_chooser_button_set_title        (GtkFileChooserButton *button,
    								const gchar          *title);
    gint                  gtk_file_chooser_button_get_width_chars  (GtkFileChooserButton *button);
    void                  gtk_file_chooser_button_set_width_chars  (GtkFileChooserButton *button,
    								gint                  n_chars);
    gboolean              gtk_file_chooser_button_get_focus_on_click (GtkFileChooserButton *button);
    void                  gtk_file_chooser_button_set_focus_on_click (GtkFileChooserButton *button,
                                                                      gboolean              focus_on_click);
    
    G_END_DECLS
    
    #endif /* !__GTK_FILE_CHOOSER_BUTTON_H__ */
    and here's a cut-down version of the header file for GtkFileChooser (showing function gtk_file_chooser_get_filename() at the end):-

    Code:
    #if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
    #error "Only <gtk/gtk.h> can be included directly."
    #endif
    
    #ifndef __GTK_FILE_CHOOSER_H__
    #define __GTK_FILE_CHOOSER_H__
    
    #include <gtk/gtkfilefilter.h>
    #include <gtk/gtkwidget.h>
    
    G_BEGIN_DECLS
    
    #define GTK_TYPE_FILE_CHOOSER             (gtk_file_chooser_get_type ())
    #define GTK_FILE_CHOOSER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser))
    #define GTK_IS_FILE_CHOOSER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_CHOOSER))
    
    typedef struct _GtkFileChooser      GtkFileChooser;
    
    typedef enum
    {
      GTK_FILE_CHOOSER_ACTION_OPEN,
      GTK_FILE_CHOOSER_ACTION_SAVE,
      GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
      GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
    } GtkFileChooserAction;
    
    typedef enum
    {
      GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM,
      GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME,
      GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN
    } GtkFileChooserConfirmation;
    
    GType gtk_file_chooser_get_type (void) G_GNUC_CONST;
    
    /* GError enumeration for GtkFileChooser */
    /**
     * GTK_FILE_CHOOSER_ERROR:
     *
     * Used to get the #GError quark for #GtkFileChooser errors.
     */
    #define GTK_FILE_CHOOSER_ERROR (gtk_file_chooser_error_quark ())
    
    typedef enum {
      GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
      GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
      GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
      GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME
    } GtkFileChooserError;
    
    GQuark gtk_file_chooser_error_quark (void);
    
    /* Filename manipulation */
    gchar *  gtk_file_chooser_get_filename       (GtkFileChooser *chooser);
    
    /* ... and all the other function declarationss */
    
    G_END_DECLS
    
    #endif /* __GTK_FILE_CHOOSER_H__ */
    The programmer creates a button and uses it like this:-

    Code:
    GtkWidget* file_chooser_button = gtk_file_chooser_button_new ("Choose a file", GTK_FILE_CHOOSER_ACTION_OPEN);
    
    // Then - after the user has chosen his file:-
    
    gchar* chosen_file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_chooser_button));
    Thanks for persevering so far! Here's the bit I don't understand.... GTK_FILE_CHOOSER() effectively casts a GtkFileChooserButton* to a GtkFileChooser*. But looking at the two header files I can't see anything that would allow one object to be cast to the other. And yet it does work! What am I failing to see
    Last edited by John E; May 4th, 2011 at 05:38 AM.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  2. #2
    Join Date
    Aug 2008
    Location
    Scotland
    Posts
    379

    Re: Trying to get my head around GTK+ casting

    Hi,

    I guess it comes down to what does G_TYPE_CHECK_INSTANCE_CAST do?
    I don't know the answer, but what I find useful for something like this is to expand out all the macros to see the code that will be compiled. That might make it clearer.

  3. #3
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867

    Re: Trying to get my head around GTK+ casting

    Well, I guess that's the confusing thing. G_TYPE_CHECK_INSTANCE_CAST checks that the supplied object is of a particular type and returns it, cast to that type:-

    G_TYPE_CHECK_INSTANCE_CAST

    Most often it's used if you have some kind of GtkObject* (let's say a GtkWidget*) and you need to check if the widget is say, a GtkButton or a GtkLabel or a GtkDialog or whatever.

    But what's confusing me is that a GtkFileChooserButton is NOT a type of GtkFileChooser (from what I can tell, anyway). I don't understand the mechanism by which one can be cast to the other.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  4. #4
    Join Date
    Aug 2008
    Location
    Scotland
    Posts
    379

    Re: Trying to get my head around GTK+ casting

    Well, looks like the call expands out to something like:

    ((GtkFileChooser)*) g_type_check_instance_cast ((GTypeInstance*) file_chooser_button, gtk_file_chooser_get_type ())

    so there's a cast to (GTypeInstance*) in between which maybe explains it.

  5. #5
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Trying to get my head around GTK+ casting

    http://developer.gnome.org/gtk/2.24/GtkFileChooser.html

    Note this statement:
    "GtkFileChooser is implemented by GtkFileChooserButton, GtkFileChooserDialog and GtkFileChooserWidget."

    This implies that even though GtkFileChooserButton is not strictly under GtkFileChooser in the hierarchy, they are related in some castable way. Let GTK worry about the details, it will throw a warning if it can't do the conversion.

  6. #6
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867

    Re: Trying to get my head around GTK+ casting

    You're right Lindley. The key is just to trust that it works and not worry about 'how' it works. At first I assumed it must have something to do with the inbuilt private data members but when I was experimenting the other day, even a standard 'C' style cast seemed to work IIRC - i.e.

    Code:
    GtkWidget* file_chooser_button = gtk_file_chooser_button_new ("Choose a file", GTK_FILE_CHOOSER_ACTION_OPEN);
    
    // Then - after the user has chosen his file:-
    
    gchar* chosen_file = gtk_file_chooser_get_filename ((GtkFileChooser*)file_chooser_button);
    At least I think it did. Maybe it didn't - I'll give it another try later.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  7. #7
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867

    Re: Trying to get my head around GTK+ casting

    Yes, a conventional 'C' style cast also works which is hardly surprising because, if GTK_FILE_CHOOSER(obj) succeeds, it simply returns the same address it was given.

    I'm really curious to know how this works. How can the same memory address point to two (apparently) different objects?

    Looking back at the header file for GtkFileChooser I noticed that it's typedef'd like so:-

    Code:
    typedef struct _GtkFileChooser      GtkFileChooser;
    but struct _GtkFileChooser is never defined anywhere. Does this give us any clue as to what's going on?
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  8. #8
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Trying to get my head around GTK+ casting

    Quote Originally Posted by Lindley View Post
    Let GTK worry about the details, it will throw a warning if it can't do the conversion.
    Main principal of “design by contract” approach: “Trust me…”
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  9. #9
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Trying to get my head around GTK+ casting

    Quote Originally Posted by John E View Post
    Yes, a conventional 'C' style cast also works which is hardly surprising because, if GTK_FILE_CHOOSER(obj) succeeds, it simply returns the same address it was given.

    I'm really curious to know how this works. How can the same memory address point to two (apparently) different objects?
    For that to work you “only” need to make sure that the functions you call are at the same offset.
    That might be a clue:
    Code:
      void (*__gtk_reserved1);
      void (*__gtk_reserved2);
      void (*__gtk_reserved3);
      void (*__gtk_reserved4);
      void (*__gtk_reserved5);
      void (*__gtk_reserved6);
      void (*__gtk_reserved7);
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  10. #10
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867

    Re: Trying to get my head around GTK+ casting

    Vladimir - I did wonder about that but there are only seven reserved function addresses whereas gtkfilechooser.h offers dozens of functions that can be called (to keep things short I only showed one function declaration but in reality, there are about 70 others.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  11. #11
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Trying to get my head around GTK+ casting

    I’ve downloaded Gtk+ source code, started to track down some macro definitions, but life is too short!
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  12. #12
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,867

    Re: Trying to get my head around GTK+ casting

    Oh, please don't bother on my account Vladimir..! There's one helluva lot of code in GTK+ (and that's without all the extra stuff you'll need like Glib etc). Given enough time I can definitely figure this out for myself but it'll be a time consuming job, as you discovered.

    I just thought it might save me some effort at my end if somebody already understood the mechanism.

    Thanks for your efforts anyway.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  13. #13
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Trying to get my head around GTK+ casting

    Quote Originally Posted by John E View Post
    Oh, please don't bother on my account ...
    No worries. I was curious to see how it is done.
    Keep in mind: this is C, not C++. Could they have overloaded cast operator? May be you are just lucky to get the same pointer, but if you cast to a different class – you’d get different pointer?
    May be all types declare all functions, and their run-time decides what to call? (This is a bit “out there”).
    Anyway, I AM still a little curious; will monitor this thread.
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  14. #14
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Trying to get my head around GTK+ casting

    take a look here, the concepts/tutorials sections explain the structure of the GTK type system and the reference material delves with the underlying mechanism in depth ...

    ... uhm, after reading the first three subsections every word starting with "G" starts giving me nausea ... ... hope never need to program with GTK !

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured