Search code examples
ccastingc-preprocessor

Make a macro for pointer struct


I need to make a macro to typecast (right word?) pointer struct from a function parameter. This is my struct:

typedef struct _AppData {
    GtkWidget* toplevel; // main window
    GtkWidget* view; // column style view
    GtkWidget* entry_outdir; // output dir
    GtkWidget* entry_artist; // artist
    GtkWidget* entry_title; // title
    GtkWidget* entry_link; // link
    GtkWidget* check_jman; // bool for jman
    GtkWidget* menuitem_clear; // init states
    GtkWidget* menuitem_action; // play/stop menu item
} AppData, *PAppData;

somewhere in my code is used like this:

g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cb_select_folder), pad);
void cb_select_folder (GtkButton* sender, gpointer user_data)
{
  PAppData pad = PAPPDATA(user_data); // typecast macro here
  const gchar* dirname = gtk_entry_get_text (GTK_ENTRY(pad->entry_outdir));
  // ..
}

To create the macro I'm trying this:

#define PAPPDATA(_in_) (PAppData(_in_))

and I get error: expected ‘)’ before ‘user_data’ Any help?


Solution

  • In C you don't have to cast a (void*) to it's final type. When using glib, gpointer is a typedef for a void*. Hence, no casting is nessesary. You do need to be sure, that the type is correct, otherwise you're in trouble.

    void cb_select_folder (GtkButton* sender, gpointer user_data)
    {
      PAppData pad = user_data; // No cast Necessary.
      const gchar* dirname = gtk_entry_get_text (GTK_ENTRY(pad->entry_outdir));
      // ..
    }
    

    The GTK_ENTRY(pad->entry_outdir), actually does a cast, but that is because it's casting between two different kinds of pointers, from GtkWidget* to GtkEntry*. In addition to the cast, It also does some runtime checking whether the GtkWidget* is actually a GtkEntry*, you probably get a runtime warning when doing this cast when pad->entry_outdir turns out to be pointing to something else than a GtkEntry. But in GObject speak, GtkEntry is a GtkWidget and GtkWidget is an GObject. You PAppData is a plain pointer to struct and not a GObject.