多次包含仅标题库时重复符号

  • 本文关键字:符号 包含仅 标题 c
  • 更新时间 :
  • 英文 :


我为我正在制作的一个小游戏制作了一个简单的辅助库。在这样的库中,我有一些核心函数必须尽可能快地执行,因为它们每个游戏帧被调用数千次。

如果我将它们声明为"内联"并将它们的声明(library.h)与它们的实现(library.c)分开并将它们包含在游戏文件(game.c)中,我想它们没有内联/优化,因为直接在game.c中声明它们并使用gcc -O3编译游戏,使性能提升了60倍以上。

为了解决这个问题,我决定将我的库设置为仅标题库。我所有的框架常量、变量和函数都在library.h.将其包含在game.c中仍然可以为我提供最大的性能。

现在,问题是每当我在多个文件(例如game1.cgame2.c)中包含library.h时,我在编译游戏时都会收到一长串duplicate symbol错误。库已#pragma once,但问题仍然存在。

如何实际编写仅标头库或确保来自外部库的内联函数实际上得到了优化?

谢谢

正如alk已经评论的那样,您需要在头文件中声明函数和全局变量static

static关键字表示对象(函数或变量)具有内部链接;它仅在当前编译单元中可见,并且不会包含在任何符号表中。

使用 include 保护也是一个好主意,这样,如果您有另一个包含头文件的头文件,并且 C 源文件同时包含您的头文件和另一个头文件,则您的头文件只会包含一次。(在下面的示例中,带有FOOLIB_H的行构成了包含保护。

考虑以下简单的固定大小堆栈示例foolib.h

#ifndef   FOOLIB_H
#define   FOOLIB_H
#include <stdlib.h>
#define   STACK_MAX  256
static size_t  stack_size = 0;
static double  stack_item[STACK_MAX];
static inline int  stack_push(const double  item)
{
if (stack_size < STACK_MAX) {
stack_item[stack_size++] = item;
return 0;
} else
return -1;
}
static inline double  stack_pop(const double  empty)
{
if (stack_size > 0)
return stack_item[--stack_size];
else
return empty;
}
#endif /* FOOLIB_H */

包含上述内容(#include "foolib.h")的每个编译单元(您单独编译的每个源文件)都会获得自己的本地私有堆栈,它们可以通过stack_push()stack_pop()使用。

将函数标记为static inline而不仅仅是static的原因是,前者告诉编译器,如果不使用它,可以完全省略该函数。特别是,如果使用gcc -Wall编译代码,gcc 会在不使用static函数时发出警告,但在不使用static inline函数时不会发出警告。除此之外,没有太大的实际区别。

最新更新