如何使从外部访问函数显而易见?


9

这是一个特定于C的问题。我试图将所有可能的内容都保留在翻译单元的边界之内,仅通过.h文件公开一些功能。也就是说,我正在static链接到文件级对象。

现在,其他模块需要调用几个函数,而不是直接调用。我的模块/文件/翻译单元订阅其他模块,将指针传递给函数。然后,在发生特定事件时,将使用一些参数来调用指针。

因此,我想知道如何使这些功能从某个晦涩难懂的位置调用变得非常明显。

  • 它们应该是static还是extern(并将它们显示在中.h)?
  • 我应该在函数名称中包含一些提示吗?
  • 还是发表一个“由X调用”的评论就足够了?

1
这是一个很好的问题。我的解决方案(我一点都不高兴,这就是为什么我只在注释中添加它)是使多个头文件合理地命名,并在希望它们具有的作用域上对函数进行分组。对于AStar库,我已经拥有AStar.h,AStar_private.h,AStar_packagePrivate.h等...
Shivan Dragon 2014年

Answers:


2

从编译单元(文件)的角度来看,您唯一需要关注的是外部是否可以使用该功能。使其可用意味着要调用它,并且您应该在那些调用将要发生的假设下进行操作。您对函数本身的关注始于其入口点。控制首先如何到达那里仅与实现它的代码有关。

由于CI的每个实现中的链接都是符号性的,因此调用函数的任何事物都必须引用其符号:

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

如果您错误地声明foo()static,则您的程序将不会链接。如果您将其声明为non- static,则有一个未调用的公开函数。通过转储目标文件的符号表或在源代码中搜索它,可以解决有关是否使用功能的问题。


1

因此,我在徘徊如何使那些函数从某个晦涩的位置被调用变得非常明显。

定义“模糊”。
方法应该通过定义明确的“接口”公开,并且正如Shivan Dragon已经建议的那样,这些“接口” 您的.h文件。如果您没有给另一个程序“正确的”头文件,那么它将无法调用该方法。

它们应该是静态的还是外部的(并将它们显示在.h中)?

static 可能是OK,只要你没有任何类[样结构]包含实例数据。
extern意味着实际上根本没有实现它;在链接过程中从其他地方“获取”实现。

我应该在函数名称中包含一些提示吗?

还是发表一个“由X调用”的评论就足够了?

绝对不。

这样的注释,无论多么好意,在您完成编写时就已过时。


解决您的第一点时,这些函数的调用如下。我的组件包括一个外部.h文件。它从那里调用一个函数,并为其提供指向模块自身函数之一的指针。后来,外部代码调用该指针处的内容。因此,某人正在调用我的函数,该人不包括我的头文件,而是包括他的头文件。
Vorac 2014年

1
关于第二点,据我所知,默认情况下,在文件范围内定义的对象具有外部链接。因此extern关键字是多余的
Vorac 2014年

0

如果在模块中定义了回调函数,并且用户永远不会提供回调函数,那么我认为您可以在初始化阶段使用占位符。占位符通常是enum,然后在内部将其转换为正确的static函数。


0

我仍将使它们static(它们不打算被任何人链接和调用),并将其用途标记为以其名称提供给外部函数的回调。

static 因为我会尽量隐藏自己可以隐藏的东西。

用它们的名称标记它们,因为a),注释已过时,以及b),在提供回调的位置,该函数旨在以这种方式使用变得很明显:这基本上使它成为一个危险标记使用不遵循命名约定的函数的地址。


0

范围修饰符应主要用作编译器的信息,而不是“足够接近”的文档形式。static特别是,使用C可使C编译器使该函数无法在模块外部使用,包括用作回调-不是您想要的,即使它可以与当前的编译器一起使用。

当然,您应该在代码中添加注释,因为您会看到它是一种潜在的混乱情况。任何异常或意外的情况都需要适当的注释。但是,正如其他答案所述,评论可能无法阅读或过时。

因此,剩下的唯一选择是命名函数以指示它是回调。我见过的大多数示例都使用_callback_cb作为后缀,或cb_作为前缀。如果回调在代码中不常见,则使用长格式;如果它们很常见,则使用短格式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.