如何判断方法函数指针是否属于GObject中的实例结构或类结构?

时间:2015-12-23 07:25:38

标签: c ubuntu gstreamer glib gobject

在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];
};

您可以通过上面的代码片段看到实例结构和类结构中的函数方法指针。 intance函数方法指针由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
}

所以我混淆了这个问题,为什么在intance结构中有函数方法指针而不是放入类类结构?

1 个答案:

答案 0 :(得分:1)

方法函数指针属于类结构。这适用于任何虚拟方法(可以在继承类中重写的方法)。

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

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

GObject参考手册illustrates these scenariosthe "Non-virtual public methods" section显示正常情况,而不是在实例结构中声明函数指针。

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

  

创建一个pad的GstElement通常会使用各种gst_pad_set _ * _ function()调用来为pad上的事件,查询或数据流注册回调。

因此activatefunc成员存储一个指向回调函数的指针,该回调函数在激活填充时被调用,对于其余的函数指针也类似。这是有道理的,因为回调函数更像是具有的对象,而不是对象本身的一部分。

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

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

我的猜测是GStreamer设计师选择了他们想要的更简单的实现

  • 允许GStreamer与可能本身不使用GObject框架的现有C代码一起使用,并且
  • 通过最小化调用回调例程所需的链接函数调用次数来保持低延迟(在多媒体应用程序中至关重要)。