C中的GObject子类无法创建子类实例

问题描述:

我想尝试GObject API。这个想法是创建一个Vehicule类,它是一个DERIVABLE类型,并创建一个名为Car的子类Vehicule,它是一个FINAL类型。我的问题是,当我尝试在一个小程序中创建一个类Car时,我的程序块并不会在创建实例时返回。C中的GObject子类无法创建子类实例

以下是重现我的问题的最小代码。我使用惯例tuto-vehicule/tuto-car。

的tuto-vehicule.h

#ifndef __TUTO_VEHICULE_H__ 
#define __TUTO_VEHICULE_H__ 
#include <glib-object.h> 

G_BEGIN_DECLS 

typedef struct _TutoVehiculePrivate { 
    GObject parent_instance; 
    GString *name; 
    guint nb_wheels; 
} TutoVehiculePrivate; 

typedef struct _TutoVehiculeClass { 
    GObjectClass parent_class; 
} TutoVehiculeClass; 

#define TUTO_TYPE_VEHICULE tuto_vehicule_get_type() 
G_DECLARE_DERIVABLE_TYPE(TutoVehicule, tuto_vehicule, TUTO, VEHICULE, GObject); 


TutoVehicule *tuto_vehicule_new (void); 

void tuto_vehicule_set_name(TutoVehicule *self, gchar *name); 
void tuto_vehicule_set_nb_wheels(TutoVehicule *self, gint nb_wheels); 
void tuto_vehicule_print_name(TutoVehicule *self); 
void tuto_vehicule_print_nb_wheels(TutoVehicule *self); 

G_END_DECLS 

#endif 

的tuto-vehicule.c

#include "tuto-vehicule.h" 
#include <stdio.h> 

G_DEFINE_TYPE_WITH_PRIVATE(TutoVehicule, tuto_vehicule, G_TYPE_OBJECT); 

static void 
tuto_vehicule_dispose(GObject *object) 
{ 
    TutoVehiculePrivate *priv = tuto_vehicule_get_instance_private(TUTO_VEHICULE(object)); 
    printf("tuto_vehicule_dispose\n"); 
    g_string_free(priv->name, TRUE); 
    G_OBJECT_CLASS(tuto_vehicule_parent_class)->dispose(object); 
} 

static void 
tuto_vehicule_class_init(TutoVehiculeClass *klass) 
{ 
    GObjectClass *g_object_class = G_OBJECT_CLASS(klass); 
    /* instance destructor*/ 
    g_object_class->dispose = tuto_vehicule_dispose; 
    printf("tuto_vehicule_class_init for TutoVehiculeClass created by G_DECLARE_DERIVABLE_TYPE\n"); 
} 

static void 
tuto_vehicule_init(TutoVehicule *self) 
{ 
    TutoVehiculePrivate *priv = tuto_vehicule_get_instance_private(self); 
    priv->name = g_string_new(NULL); 
    priv->nb_wheels = 0; 
    printf("tuto_vehicule_init\n"); 
} 

TutoVehicule * 
tuto_vehicule_new(void) 
{ 
    TutoVehicule *vehicule_instance = g_object_new(TUTO_TYPE_VEHICULE, NULL); 
    return vehicule_instance; 
} 

void tuto_vehicule_set_name(TutoVehicule *self, gchar *name) 
{ 
    TutoVehiculePrivate *priv = tuto_vehicule_get_instance_private(self); 
    g_string_assign(priv->name, name); 
} 

void tuto_vehicule_set_nb_wheels(TutoVehicule *self, gint nb_wheels) 
{ 
    TutoVehiculePrivate *priv = tuto_vehicule_get_instance_private(self); 
    priv->nb_wheels = nb_wheels; 
} 

void tuto_vehicule_print_name(TutoVehicule *self) 
{ 
    TutoVehiculePrivate *priv = tuto_vehicule_get_instance_private(self); 
    printf("Vehicule name: %s\n", priv->name->str); 
} 

void tuto_vehicule_print_nb_wheels(TutoVehicule *self) 
{ 
    TutoVehiculePrivate *priv = tuto_vehicule_get_instance_private(self); 
    printf("Vehicule number of wheels: %d\n", priv->nb_wheels); 
} 

的tuto-car.h

#ifndef __TUTO_CAR_H 
#define __TUTO_CAR_H 
#include "tuto-vehicule.h" 
#include <glib-object.h> 

G_BEGIN_DECLS 

#define TUTO_TYPE_CAR tuto_car_get_type() 
G_DECLARE_FINAL_TYPE(TutoCar, tuto_car, TUTO, CAR, TutoVehicule); 

typedef struct _TutoCar { 
    TutoVehicule parent_instance; 
} TutoCar; 

TutoCar *tuto_car_new(void); 
void tuto_car_print_name(TutoCar *self); 
void tuto_car_print_nb_wheels(TutoCar *self); 
G_END_DECLS 
#endif 

政党成员,car.c

#include "tuto-car.h" 
#include <stdio.h> 

G_DEFINE_TYPE(TutoCar, tuto_car, TUTO_TYPE_CAR); 

static void 
tuto_car_class_init(TutoCarClass *klass) 
{ 
    printf("tuto_car_class_init\n"); 
} 

static void 
tuto_car_init(TutoCar *self) 
{ 
    printf("tuto_car_init\n"); 
} 

TutoCar * 
tuto_car_new(void) 
{ 
    TutoCar *car = g_object_new(TUTO_TYPE_CAR, NULL); 
    tuto_vehicule_set_name(TUTO_VEHICULE(car), "car"); 
    tuto_vehicule_set_nb_wheels(TUTO_VEHICULE(car), 4); 
    return car; 
} 

void 
tuto_car_print_name(TutoCar *self) 
{ 
    tuto_vehicule_print_name(TUTO_VEHICULE(self)); 
} 

void 
tuto_car_print_nb_wheels(TutoCar *self) 
{ 
    tuto_vehicule_print_nb_wheels(TUTO_VEHICULE(self)); 
} 

我用这两个班在一个简单的主文件:

#include <stdio.h> 
#include "tuto-vehicule.h" 
#include "tuto-car.h" 

int main(int argc, char **argv) 
{ 
    printf("Create a TutoVehicule instance\n"); 

    TutoVehicule *moto = tuto_vehicule_new(); 
    printf("Puts its name to moto\n"); 
    tuto_vehicule_set_name(moto, "moto"); 
    printf("Puts its number of wheels to 2\n"); 
    tuto_vehicule_set_nb_wheels(moto, 2); 

    printf("Create a TutoCar instance\n"); 
    TutoCar *car = tuto_car_new(); 

    printf("Use methods instance\n"); 

    tuto_vehicule_print_name(moto); 
    tuto_vehicule_print_nb_wheels(moto); 

    tuto_vehicule_print_name(TUTO_VEHICULE(car)); 
    tuto_vehicule_print_nb_wheels(TUTO_VEHICULE(car)); 

    tuto_car_print_name(car); 
    tuto_car_print_nb_wheels(car); 

    printf("Destroy the instances created previously\n"); 
    g_object_unref(car); 
    g_object_unref(moto); 

    return 0; 
} 

编译工作与:

gcc -Wall -o main_vehicule `pkg-config --libs --cflags gobject-2.0` main_vehicule.c tuto-car.c tuto-vehicule.c 

但是当我运行该程序,正如我下面所说,我有这个输出和程序块没有返回,也没有发出错误消息:

Create a TutoVehicule instance 
tuto_vehicule_class_init for TutoVehiculeClass created by G_DECLARE_DERIVABLE_TYPE 
tuto_vehicule_init 
Puts its name to moto 
Puts its number of wheels to 2 
Create a TutoCar instance 

我知道,在这个声明我的程序块:

TutoCar *car = g_object_new(TUTO_TYPE_CAR, NULL); 

有什么我错过了?官方文件不是很清楚。

编辑

这里是一个GDB会话:

(gdb) break tuto-car.c:tuto_car_new 
Breakpoint 1 at 0x400dcb: file tuto-car.c, line 21. 
(gdb) run 
Starting program: /home/cedlemo/Projets/C/GObject/derivable_type/main_vehicule 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/usr/lib/libthread_db.so.1". 
Create a TutoVehicule instance 
tuto_vehicule_class_init for TutoVehiculeClass created by G_DECLARE_DERIVABLE_TYPE 
tuto_vehicule_init 
Puts its name to moto 
Puts its number of wheels to 2 
Create a TutoCar instance 

Breakpoint 1, tuto_car_new() at tuto-car.c:21 
21  TutoCar *car = g_object_new(TUTO_TYPE_CAR, NULL); 
(gdb) backtrace 
#0 tuto_car_new() at tuto-car.c:21 
#1 0x0000000000400c02 in main (argc=1, argv=0x7fffffffded8) at main_vehicule.c:16 
(gdb) next 

在gdb程序段太让我不得不打CTRL + Ç和检查堆栈:

(gdb) backtrace 
#0 0x00007ffff75ba269 in syscall() from /usr/lib/libc.so.6 
#1 0x00007ffff790618f in g_cond_wait() from /usr/lib/libglib-2.0.so.0 
#2 0x00007ffff78e8437 in g_once_init_enter() from /usr/lib/libglib-2.0.so.0 
#3 0x0000000000400d1e in tuto_car_get_type() at tuto-car.c:4 
#4 0x0000000000400d44 in tuto_car_get_type() at tuto-car.c:4 
#5 0x0000000000400dd0 in tuto_car_new() at tuto-car.c:21 
#6 0x0000000000400c02 in main (argc=1, argv=0x7fffffffded8) at main_vehicule.c:16 
+0

请注意以下几点:“请注意,以双下划线或下划线和大写字母开头的符号是无条件地保留用于实现的,是的,系统标头使用带有双下划线的名称 - 它们是实现的一部分并且不允许污染你​​的名字空间,你不应该污染他们的名字空间,尽管所有的实际用途和多个反例,尽管如此,还是要把下划线开头的名字作为编译器保留下来。“ – user3629249

+0

@ user3629249,如果你引用以_TutoCar或_TutoVehiculePrivate为例,我只是遵循GObject约定,请参阅:https://developer.gnome.org/gobject/2.48/howto-gobject.html或https://developer.gnome.org/gobject/2.48/ howto-gobject-code.html – cedlemo

+0

我意识到,这实际上是一个很小的例子,因为GObject代码很遗憾;你可以通过削减车轮属性的名称和数量来使其更加小巧,并查看是否会影响到任何内容。在任何情况下,我都会使用一个调试器来查看程序正在冻结的位置,而不是依赖于打印语句。现在,我会投票重新开始,因为我认为问题陈述很清楚。 – ptomato

下面是答案:

在文件tuto-car中。C,我一个行:

G_DEFINE_TYPE(TutoCar, tuto_car, TUTO_TYPE_CAR); 

两个宏:

  • G_DEFINE_TYPE
  • G_DEFINE_TYPE_WITH_PRIVATE

最后一个参数是父的G-类。在我的代码中,我使用了它自己的类的GType。我应该用TUTO_TYPE_VEHICULE

G_DEFINE_TYPE(TutoCar, tuto_car, TUTO_TYPE_VEHICULE); 

有了这个以前的代码完全工作。