Подклассы GObject в C не могут создать экземпляр подкласса
Я хотел попробовать GObject API. Идея состоит в том, чтобы создать класс ГИБДД, который является DERIVABLE
введите и создайте подкласс из автомобиля под названием "Автомобиль", который является FINAL
тип. Моя проблема в том, что когда я пытаюсь в маленькой программе создать класс Car, мой программный блок не возвращается при создании экземпляра.
Вот минимальный код для воспроизведения моей проблемы. Я использую соглашение tuto-vehicleule /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
Tuto-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+C и проверить стек:
(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
1 ответ
Вот ответ:
в файле tuto-car.c есть строка:
G_DEFINE_TYPE(TutoCar, tuto_car, TUTO_TYPE_CAR);
для двух макросов:
G_DEFINE_TYPE
G_DEFINE_TYPE_WITH_PRIVATE
последний параметр - это GType родителя. В своем коде я использовал GType этого класса. Я должен был использовать TUTO_TYPE_VEHICULE
G_DEFINE_TYPE(TutoCar, tuto_car, TUTO_TYPE_VEHICULE);
При этом предыдущий код полностью работает.