gpt4 book ai didi

c - 如何确定方法函数指针属于 GObject 的实例结构还是类结构?

转载 作者:行者123 更新时间:2023-11-30 15:13:41 27 4
gpt4 key购买 nike

以 glib GObject 为例:

typedef struct _MyInstance MyInstance;
struct _MyInstance {
GObject parent;
......//instance variable
......//this place is method function pointer in instance structure.
};

typedef struct _MyInstanceClass MyInstanceClass;
struct _MyInstanceClass {
GObjectClass parent_class;
......//class variable
......//this place is method function pointer in class structure.
};

我不明白方法函数指针放入它所看到的相同的类或实例结构中。它们有什么区别?我认为每个实例对象的类函数方法指针都用于调用相同的函数,因此将此函数放入类结构中。但是,如何使用实例对象的函数方法指针来代替它自己的方法指针呢?因为我认为实例对象的函数方法指针对于自身来说是相同的,如何理解实例对象的函数方法?下面我给出 gstreamer Gstpad.h 代码片段作为示例:

struct _GstPad {
GstObject object;

/*< public >*/
gpointer element_private;

GstPadTemplate *padtemplate;

GstPadDirection direction;

/*< public >*/ /* with STREAM_LOCK */
/* streaming rec_lock */
GStaticRecMutex *stream_rec_lock;
GstTask *task;
/*< public >*/ /* with PREROLL_LOCK */
GMutex *preroll_lock;
GCond *preroll_cond;

/*< public >*/ /* with LOCK */
/* block cond, mutex is from the object */
GCond *block_cond;
GstPadBlockCallback block_callback;
gpointer block_data;

/* the pad capabilities */
GstCaps *caps;
GstPadGetCapsFunction getcapsfunc;
GstPadSetCapsFunction setcapsfunc;
GstPadAcceptCapsFunction acceptcapsfunc;
GstPadFixateCapsFunction fixatecapsfunc;

GstPadActivateFunction activatefunc;
GstPadActivateModeFunction activatepushfunc;
GstPadActivateModeFunction activatepullfunc;

/* pad link */
GstPadLinkFunction linkfunc;
GstPadUnlinkFunction unlinkfunc;
GstPad *peer;

gpointer sched_private;

/* data transport functions */
GstPadChainFunction chainfunc;
GstPadCheckGetRangeFunction checkgetrangefunc;
GstPadGetRangeFunction getrangefunc;
GstPadEventFunction eventfunc;

GstActivateMode mode;

/* generic query method */
GstPadQueryTypeFunction querytypefunc;
GstPadQueryFunction queryfunc;

/* internal links */
#ifndef GST_DISABLE_DEPRECATED
GstPadIntLinkFunction intlinkfunc;
#else
#ifndef __GTK_DOC_IGNORE__
gpointer intlinkfunc;
#endif
#endif

GstPadBufferAllocFunction bufferallocfunc;

/* whether to emit signals for have-data. counts number
* of handlers attached. */
gint do_buffer_signals;
gint do_event_signals;

/* ABI added */
/* iterate internal links */
GstPadIterIntLinkFunction iterintlinkfunc;

/* free block_data */
GDestroyNotify block_destroy_data;

/*< private >*/
union {
struct {
gboolean block_callback_called;
GstPadPrivate *priv;
} ABI;
gpointer _gst_reserved[GST_PADDING - 2];
} abidata;
};

struct _GstPadClass {
GstObjectClass parent_class;

/* signal callbacks */
void (*linked) (GstPad *pad, GstPad *peer);
void (*unlinked) (GstPad *pad, GstPad *peer);
void (*request_link) (GstPad *pad);
gboolean (*have_data) (GstPad *pad, GstMiniObject *data);

/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};

从上面的代码片段中可以看到实例结构和类结构中的函数方法指针。实例函数方法指针由gst_pad_init函数初始化,如下:

static void
gst_pad_init (GstPad * pad)
{
........//other no important code
GST_PAD_CHAINFUNC (pad) = NULL;
GST_PAD_LINKFUNC (pad) = NULL;
GST_PAD_CAPS (pad) = NULL;
GST_PAD_GETCAPSFUNC (pad) = NULL;
GST_PAD_ACTIVATEFUNC (pad) = gst_pad_activate_default;
GST_PAD_EVENTFUNC (pad) = gst_pad_event_default;
GST_PAD_QUERYTYPEFUNC (pad) = gst_pad_get_query_types_default;
GST_PAD_QUERYFUNC (pad) = gst_pad_query_default;
#ifndef GST_REMOVE_DEPRECATED
GST_PAD_INTLINKFUNC (pad) = gst_pad_get_internal_links_default;
#endif
GST_PAD_ITERINTLINKFUNC (pad) = gst_pad_iterate_internal_links_default;

GST_PAD_ACCEPTCAPSFUNC (pad) = gst_pad_acceptcaps_default;

............//other no important code
}

所以我很困惑这个问题,为什么实例结构中有函数方法指针而不是放入类类结构中?

最佳答案

方法函数指针属于类结构。对于任何虚拟方法(可以在继承类中重写的方法)都是如此。

实例结构中声明函数指针意味着相应的方法仅在该特定类的对象上定义,并且不能被覆盖(非虚拟)。

但是,在这种情况下,根本不需要公开函数指针,因为永远不会有该方法的多个实现,因此对于调用哪个实现永远不会有任何歧义。遵循 GObject 约定,您只需在头文件中声明一个与该方法相对应的函数,然后在源文件中提供一个实现。

GObject 引用手册 illustrates these scenarios ,与 the "Non-virtual public methods" section显示通常执行的操作,而不是在实例结构中声明函数指针。

<小时/>

您粘贴的 GStreamer 代码显示了上述情况的一个异常(exception)。在该代码中,存储在实例结构中的函数指针实际上是 GstPad 对象的属性,而不是在对象本身上定义的方法。 The description of the class

A GstElement creating a pad will typically use the various gst_pad_set_*_function() calls to register callbacks for events, queries or dataflow on the pads.

因此,activatefunc 成员存储一个指向回调函数的指针,该函数在激活 pad 时调用,例如,对于其余函数指针也类似。这是有道理的,因为回调函数更多的是对象拥有的东西,而不是对象本身本质的一部分。

也就是说,确实更纯粹的面向对象实现可能

  • 直接在类本身中实现回调方法,期望它们在每个应用程序唯一的子类中被重写;或
  • 通过调用应用程序提供的实现特定回调的对象上的方法来实现回调interface .

我的猜测是 GStreamer 设计者选择了他们所做的更简单的实现

  • 允许 GStreamer 与本身可能不使用 GObject 框架的现有 C 代码一起使用,并且
  • 通过最大限度地减少调用回调例程所需的链式函数调用数量,保持较低的延迟(在多媒体应用中至关重要)。

关于c - 如何确定方法函数指针属于 GObject 的实例结构还是类结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34430659/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com