g_signal

g_signal에 대해서 알기 위해서 gobject 부터 알아야 하는데 아래 사이트에서 어느정도 잘 정리된 것 같습니다. gobject에 대해서는 아래 사이트를 참고 해주시고요.

  • http://lethean.github.io/2012/02/24/oop-with-gobject-5/
  • https://developer.gnome.org/gobject/stable/gobject-Signals.html

g시리즈 open source(gobject, guppnp, gssdp, gsoup, gstreamer, gtk,...)을  사용하여 event를 처리할 때 g_signal_connect를 사용하여 event가 발생할 때마다 등록한 함수가 호출되는 식으로 구현을 합니다.

g_signal_connect 예제는 구굴링하면 많이 찾을 수 있지만,  signal event를 등록하는 방법을 설명한 예제는 찾기가 힘듭니다.
그래서 간단히 g_signal_new 함수를 사용하여 signal event를 만들어보고 g_signal_connect 함수를 호출하여 실제 특정 event가 발생했을때 등록한 콜백함수가 호출되는 예제를 만들어봤습니다.


#include <stdio.h>
#include <iostream>
#include <string>
#include <glib-object.h>
#include <glib.h>

using namespace std;


G_BEGIN_DECLS

enum {
 NAME_CHANGED,
 SIGNAL_LAST
};

static guint signals[SIGNAL_LAST];

typedef struct
{
    GObject parent;

    gint id;
 char* name;
} Address;

typedef struct
{
    GObjectClass parent_class;
} AddressClass;

G_END_DECLS


G_DEFINE_TYPE(Address, g_address, G_TYPE_OBJECT);

static void g_address_init(Address* addr)
{
    addr->id = -1;
 addr->name = NULL;

 printf("[%s]\n", __FUNCTION__);
}

static GObject*  g_address_constructor(GType gtype, guint n_properties, GObjectConstructParam* properties)
{
 GObject* obj;

 printf("[%s]\n", __FUNCTION__);

 obj = G_OBJECT_CLASS(g_address_parent_class)->constructor(gtype, n_properties, properties);
}

static void g_address_finalize(GObject* self)
{
 Address* addr = G_TYPE_CHECK_INSTANCE_CAST(self, g_address_get_type(), Address);

 printf("[%s]\n", __FUNCTION__);

 if (addr->name != NULL)
 {
  g_free(addr->name);
  addr->name = NULL;
 }

 G_OBJECT_CLASS(g_address_parent_class)->finalize(self);
}

static void g_address_class_init(AddressClass* klass)
{
 GObjectClass* gobject_class;

 printf("[%s]\n", __FUNCTION__);

 gobject_class = G_OBJECT_CLASS(klass);

 gobject_class->constructor = g_address_constructor;
 gobject_class->finalize  = g_address_finalize;

 signals[NAME_CHANGED] = g_signal_new(
        "name-changed",
        g_address_get_type(),
        G_SIGNAL_RUN_LAST,
        0,
        NULL,
        NULL,
        g_cclosure_marshal_VOID__STRING,
        G_TYPE_NONE,
        1,
        G_TYPE_STRING);
}

Address* g_address_new()
{
 return G_TYPE_CHECK_INSTANCE_CAST(g_object_new(g_address_get_type(),NULL), g_address_get_type(), Address);
}

void g_address_set_name(Address* addr, const char* name)
{
 addr->name = g_strdup(name);
 g_signal_emit(addr, signals[NAME_CHANGED], 0, name);
}

void onNameChanged(Address* addr, gchar* value, gpointer user_data)
{
 printf("[%s] name:%s\n", __FUNCTION__, value);
}

int main()
{
 Address* addr;

 addr =  G_TYPE_CHECK_INSTANCE_CAST(g_object_new(g_address_get_type(), NULL), g_address_get_type(), Address);

 g_signal_connect(addr, "name-changed", G_CALLBACK(onNameChanged), (gpointer)0 /* user_data */);

 g_address_set_name(addr, "kang myung hun");

 g_object_unref(addr);

    return 0;
}

댓글