Search code examples
cgtkgobject

GObject sample: undefined reference to `product_finalize'?


i came from a java background and i'm trying to work with the c language. Now, java being object oriented and all, i tried to work with the GObject lib from the GTK+ project, i read some source code app (Anjuta mainly), and here is my sample code :

product.h

#pragma once

/*
class produit : id, name, price, description
*/
#include <gtk/gtk.h>
#include <glib-object.h>

/*
 * Type macros.
 */
#define TYPE_PRODUCT (product_get_type())

#define PRODUCT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_PRODUCT, Product))

#define IS_PRODUCT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_PRODUCT))

#define PRODUCT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_PRODUCT, ProductClass))

#define IS_PRODUCT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_PRODUCT))

#define PRODUCT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_PRODUCT, ProductClass))

typedef struct _Product Product;
typedef struct _ProductClass ProductClass;

struct _Product
{
    GObject parent_instance;

    gint id;
    gchar* name;
    gdouble price;
    gchar* description;
};

/* class */
struct _ProductClass
{
    GObjectClass parent_class;
};

gint product_get_id(Product* self);
void product_set_id(Product* self, gint _id);

gchar product_get_name(Product* self);
void product_set_name(Product* self, gchar* _name);

gdouble product_get_price(Product* self);
void product_set_price(Product* self, gdouble _price);

gchar product_get_description(Product* self);
void product_set_description(Product* self, gchar* _description);

void product_print(Product* self);

GType product_get_type(void);

procuct.c

#include "product.h"

G_DEFINE_TYPE(Product, product, G_TYPE_OBJECT);

static void product_finalize(GObject* obj)
{
    Product* self;

    self = PRODUCT(obj);
    g_free(self->name);
    g_free(self->description);
    G_OBJECT_CLASS(product_parent_class)->finalize(obj);
}

static void product_class_init(ProductClass* klass)
{
    G_OBJECT_CLASS(klass)->finalize = product_finalize;
}

static void product_init(Product* self)
{
    product_set_id(PRODUCT(self), 0);
    product_set_name(PRODUCT(self), "_name");
    product_set_price(PRODUCT(self), 0.0);
    product_set_description(PRODUCT(self), "_description");
}

Product* product_new(gint _id, gchar* _name, gdouble _price, gchar* _description)
{
    Product* self = NULL;
    self = (Product*)g_object_new(TYPE_PRODUCT, NULL);

    product_set_id(PRODUCT(self), _id);
    product_set_name(PRODUCT(self), _name);
    product_set_price(PRODUCT(self), _price);
    product_set_description(PRODUCT(self), _description);

    return self;
}

gint product_get_id(Product* self)
{
    g_return_if_fail(IS_PRODUCT(self));
    return self->id;
}

void product_set_id(Product* self, gint _id)
{
    g_return_if_fail(IS_PRODUCT(self));
    self->id = _id;
}

gchar product_get_name(Product* self)
{
    g_return_if_fail(IS_PRODUCT(self));
    return self->name;
}

void product_set_name(Product* self, gchar* _name)
{
    g_return_if_fail(IS_PRODUCT(self));
    self->name = _name;
}

gdouble product_get_price(Product* self)
{
    g_return_if_fail(IS_PRODUCT(self));
    return self->price;
}

void product_set_price(Product* self, gdouble _price)
{
    g_return_if_fail(IS_PRODUCT(self));
    self->price = _price;
}

gchar product_get_description(Product* self)
{
    g_return_if_fail(IS_PRODUCT(self));
    return self->description;
}

void product_set_description(Product* self, gchar* _description)
{
    g_return_if_fail(IS_PRODUCT(self));
    self->description = _description;
}

/* Object non-virtual method */
void product_print(Product* self)
{
    g_return_if_fail(IS_PRODUCT(self));

    g_print("Id - %i\n", self->id);
    g_print("nom - %s\n", self->name);
    g_print("prix - %f\n", self->price);
    g_print("description - %s\n", self->description);
}

main.c

#include <gtk/gtk.h>
#include "product.h"

int main(int argc, char* argv[])
{
    g_type_init();

    Product* bar = g_object_new(TYPE_PRODUCT, NULL);
    bar = product_new(15, "test p", 235.00,"juste");
    product_print(bar);

    product_set_price(bar, 20);
    product_set_description(bar, "c'est un succés");
    product_print(bar);
    product_finalize(bar);

    return 0;
}

nothing fancy, but i get the bunch of errors:

/bin/sh -c '/usr/bin/make -j4 -e -f  Makefile'
----------Building project:[ GTK_object_test - Debug ]----------
make[1]: Entering directory '/home/abdelghani/workspace/codelite/GTK_object_test'
cc1: warning: command line option '-std=c++11' is valid for C++/ObjC++ but not for C
/usr/bin/gcc -c  "/home/abdelghani/workspace/codelite/GTK_object_test/main.c" -g -O0 -std=c++11 -Wall -pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng12 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include   -o ./Debug/main.c.o -I. -I.
/usr/bin/gcc -c  "/home/abdelghani/workspace/codelite/GTK_object_test/product.c" -g -O0 -std=c++11 -Wall -pthread -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng12 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include   -o ./Debug/product.c.o -I. -I.
cc1: warning: command line option '-std=c++11' is valid for C++/ObjC++ but not for C
cc1: warning: command line option '-std=c++11' is valid for C++/ObjC++ but not for C
/home/abdelghani/workspace/codelite/GTK_object_test/main.c: In function 'main':
/home/abdelghani/workspace/codelite/GTK_object_test/main.c:6:5: warning: 'g_type_init' is deprecated (declared at /usr/include/glib-2.0/gobject/gtype.h:679) [-Wdeprecated-declarations]
 g_type_init();
 ^
/home/abdelghani/workspace/codelite/GTK_object_test/main.c:9:5: warning: implicit declaration of function 'product_new' [-Wimplicit-function-declaration]
 bar = product_new(15, "test p", 235.00,"juste");
 ^
/home/abdelghani/workspace/codelite/GTK_object_test/main.c:9:9: warning: assignment makes pointer from integer without a cast
 bar = product_new(15, "test p", 235.00,"juste");
 ^
/home/abdelghani/workspace/codelite/GTK_object_test/main.c:15:5: warning: implicit declaration of function 'product_finalize' [-Wimplicit-function-declaration]
 product_finalize(bar);
 ^
/home/abdelghani/workspace/codelite/GTK_object_test/product.c: In function 'product_get_name':
/home/abdelghani/workspace/codelite/GTK_object_test/product.c:65:5: warning: return makes integer from pointer without a cast
 return self->name;
 ^
/home/abdelghani/workspace/codelite/GTK_object_test/product.c: In function 'product_get_description':
/home/abdelghani/workspace/codelite/GTK_object_test/product.c:89:5: warning: return makes integer from pointer without a cast
 return self->description;
 ^
/usr/bin/g++ -o ./Debug/GTK_object_test @"GTK_object_test.txt" -L.   -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0
./Debug/main.c.o: In function `main':
/home/abdelghani/workspace/codelite/GTK_object_test/main.c:15: undefined reference to `product_finalize'
collect2: error: ld returned 1 exit status
GTK_object_test.mk:76: recipe for target 'Debug/GTK_object_test' failed
make[1]: *** [Debug/GTK_object_test] Error 1
make[1]: Leaving directory '/home/abdelghani/workspace/codelite/GTK_object_test'
Makefile:4: recipe for target 'All' failed
make: *** [All] Error 2
====2 errors, 6 warnings====

can anyone teach me whats the deal with cast warnings and the unreferenced issue?? Thx


Solution

  • There are various issues with your code example.

    You seem to be compiling this C code with a C++ compiler; don't, use a C compiler.

    You're calling:

    bar = g_object_new (...);

    right before:

    bar = product_new (...);

    which will leak the first instance.

    You're also calling product_finalize(), which is a static function — hence why you're getting a compiler error.

    The finalize() implementation will be called when the last reference on a GObject instance is dropped; you're not supposed to be calling it yourself. Use g_object_unref(), instead, to drop the reference on your object instances.