You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写C语言GObject类时,是否需自行实现new方法?

问题描述

我正在遵循GObject教程编写自己的第一个GObject类,目前已完成以下代码:

train.h

#pragma once

#include <glib-object.h>

G_BEGIN_DECLS

#define EXAMPLE_TYPE_TRAIN example_train_get_type ()
G_DECLARE_DERIVABLE_TYPE (ExampleTrain, example_train, EXAMPLE, TRAIN, GObject)

struct _ExampleTrainClass
{
  GObjectClass parent_class;

  void (* get_route) (ExampleTrain *train);
};

ExampleTrain *example_train_new (void);

G_END_DECLS

train.c

#include "train.h"

typedef struct {
  char *origin;
} ExampleTrainPrivate;

G_DEFINE_TYPE_WITH_PRIVATE (ExampleTrain, example_train, G_TYPE_OBJECT)

static void
example_train_class_init (ExampleTrainClass *klass)
{

}

static void
example_train_init (ExampleTrain *self)
{
  ExampleTrainPrivate *priv = example_train_get_instance_private (self);
}

目前代码可编译,但尝试在main.c中调用example_train_new ()实例化类时,出现以下链接错误:

[1/2] Compiling C object src/gobject-inheritance.p/main.c.o
../../../../../gobject-inheritance/src/main.c: In function ‘main’:
../../../../../gobject-inheritance/src/main.c:13:17: warning: unused variable ‘train_one’ [-Wunused-variable]
   13 |   ExampleTrain *train_one = example_train_new ();
      |                 ^~~~~~~~~
[2/2] Linking target src/gobject-inheritance
FAILED: src/gobject-inheritance 
cc  -o src/gobject-inheritance src/gobject-inheritance.p/fruit.c.o src/gobject-inheritance.p/main.c.o src/gobject-inheritance.p/train.c.o -L/app/lib -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group /usr/lib/x86_64-linux-gnu/libglib-2.0.so /usr/lib/x86_64-linux-gnu/libgobject-2.0.so -Wl,--end-group
/usr/lib/gcc/x86_64-unknown-linux-gnu/14.2.0/../../../../x86_64-unknown-linux-gnu/bin/ld: src/gobject-inheritance.p/main.c.o: in function `main':
/mnt/storage/Programming/.gnome-builder/projects/gobject-inheritance/builds/org.gnome.Example.json-flatpak-org.freedesktop.Platform-24.08-x86_64-main/../../../../../gobject-inheritance/src/main.c:13:(.text+0x10): undefined reference to `example_train_new'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

我判断问题是链接器找不到example_train_new ()的定义,虽然自行实现该方法看似合理,但教程中并未展示相关实现。请问我哪里出错了?是否需要自行实现这个new方法?


解决方案

是的,你必须自己实现example_train_new()函数。GObject提供的宏(比如G_DECLARE_DERIVABLE_TYPE和G_DEFINE_TYPE_WITH_PRIVATE)只会帮你生成类型系统核心代码(比如类型注册、私有数据访问函数),不会自动生成面向用户的构造函数。

教程里没展示这个实现,是因为它默认你理解:封装g_object_new()为类专属的构造函数是GObject开发的常规做法,这样能提供更友好的API,避免用户直接调用g_object_new()时写错类型标识符。

你只需要在train.c中添加以下实现:

ExampleTrain *
example_train_new (void)
{
  // 使用g_object_new创建实例,传入我们的类型标识符和NULL表示无属性参数
  return g_object_new(EXAMPLE_TYPE_TRAIN, NULL);
}

如果后续需要给构造函数添加参数(比如初始化origin私有属性),可以扩展成这样:

ExampleTrain *
example_train_new (const char *origin)
{
  g_return_val_if_fail(origin != NULL, NULL);
  
  ExampleTrain *train = g_object_new(EXAMPLE_TYPE_TRAIN, NULL);
  ExampleTrainPrivate *priv = example_train_get_instance_private(train);
  
  priv->origin = g_strdup(origin);
  return train;
}

同时别忘了更新train.h里的函数声明,对应修改参数列表。

链接错误的根源就是你只在头文件里声明了example_train_new(),却没有在.c文件里提供实现,导致链接器无法找到该函数的符号。


内容的提问来源于stack exchange,提问作者Newbyte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:39:58