【问题标题】:Need help in understanding this code在理解此代码方面需要帮助
【发布时间】:2011-10-21 06:54:38
【问题描述】:

在一个 gstreamer-plugin 中有一些代码:

static GstFlowReturn
gst_ebml_peek_id_full (GstEbmlRead * ebml, guint32 * id, guint64 * length,
    guint * prefix)
{
  GstFlowReturn ret;

  ret = gst_ebml_peek_id_length (id, length, prefix,
      (GstPeekData) gst_ebml_read_peek, (gpointer) gst_ebml_read_br (ebml),
      ebml->el, gst_ebml_read_get_pos (ebml));
  if (ret != GST_FLOW_OK)
    return ret;

  GST_LOG_OBJECT (ebml->el, "id 0x%x at offset 0x%" G_GINT64_MODIFIER "x"
      " of length %" G_GUINT64_FORMAT ", prefix %d", *id,
      gst_ebml_read_get_pos (ebml), *length, *prefix);

现在看到gst_ebml_peek_id_length ()的第4个参数是

(GstPeekData) gst_ebml_read_peek

其中gst_ebml_read_peek 是另一个函数,其定义为:

static const guint8 *
gst_ebml_read_peek (GstByteReader * br, guint peek)
{
  const guint8 *data = NULL;

  if (G_LIKELY (gst_byte_reader_peek_data (br, peek, &data)))
    return data;
  else
    return NULL;
}

现在我想问你的是:gst_ebml_read_peek在定义中有两个输入参数,那么如何在没有参数的情况下(在上面的代码中)调用它?

编辑: 您可以在以下位置找到此代码 http://gstreamer.freedesktop.org/data/coverage/lcov/gst-plugins-good/gst/matroska/ebml-read.c.gcov.html

从大约 194 行开始。

【问题讨论】:

  • 注: gst_ebml_read_peek(gpointer) 之间有一个逗号。
  • 写这段代码的人应该被带到外面枪杀。但我会尽力帮助你。
  • 在没有相应数据类型的情况下给我们这样的代码并不是很有用。如果GstPeekData 是对象类型的typedef,则用它来转换函数指针是UB。 gcc 通常接受这样的东西,但这不是可移植的。

标签: c


【解决方案1】:

因为它是function pointer。那个时候实际上并没有调用该函数,它只是传递给gst_ebml_peek_id_length(稍后可能会使用正确的参数调用它)。

【讨论】:

  • 值得注意的是GstPeekData 可能是const guint8 *(*)(GstByteReader *, guint)typedef
  • @BlagovestBuyukliev 很有可能,感谢您的评论。
  • 这样做有什么好处?
【解决方案2】:

这是一个做类似事情的更简单的例子:

#include <stdio.h>

typedef int (*binaryop)(int, int);

static int add(int a, int b) {
  return a + b;
}

static int mul(int a, int b) {
  return a * b;
}

static void print_result(binaryop op, int a, int b) {
  printf("%d\n", op(a, b));
}

int main() {
  print_result(add, 2, 3);
  print_result(mul, 5, 7);
  return 0;
}

print_result 函数将 另一个函数 作为参数,然后调用该参数。当您只写add 而不带括号时,该函数还没有被调用。它只在函数调用表达式中被调用,看起来像这样:function_name(arguments).

【讨论】:

  • 我接受你的回答,因为你的例子帮助我理解了这一点。谢谢你
  • 这样做有什么好处?
  • 可用于编写模块化代码。例如,可能有一个通用的排序函数qsort 可以对anything 进行排序。为此,它依赖于比较两个项目的 比较器函数。根据您传入的函数,您可以比较任意对象,而无需再次编写排序函数。
【解决方案3】:

传递给 gst_ebml_peek_id_full() 的参数是 gst_ebml_read_peek() 的函数指针,或者换句话说,它只是传递函数的句柄,以便 gst_ebml_peek_id_full() 可以使用正确的参数调用传入的函数。

提供了传递您自己/不同的函数实现的灵活性,该函数实现了 gst_ebml_read_peek() 的相同原型。

【讨论】:

    猜你喜欢
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    相关资源
    最近更新 更多