stbi_image Notes

stb_image multiple definition of first defined here 多文件包含问题

问题描述

公司代码库中stbi_image.h文件,这个库是header-only的库。 由于是只有头文件,所以其函数的声明和定义都是放在一起,所以当多个文件包含该头文件时,就会导致函数重定义的问题。

这里又分为了几种情况

  1. 只有一整个大项目进行编译
  2. 比较大型的项目,可能有多个子项目(多个lib)都依赖到stbi_image.h文件

基本使用方式

在库的stbi_image.h的文件头的doc中有如下描述:

Do this: #define STB_IMAGE_IMPLEMENTATION before you include this file in one C or C++ file to create the implementation. // i.e. it should look like this: #include ... #include ... #include ... #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"

也就是说你不能在头文件里使用STB_IMAGE_IMPLEMENTATION宏,只有定义这个这个宏才会包含函数的定义部分。因此你应该在你的源文件,也就是.c,.cpp文件里使用这个宏并包含这个头文件。

对于有多个子库都需要依赖到stbi_image.h的情况

有两种解决办法:

  1. C语言中为解决多个源文件包含相同的函数提供了解决办法------static关键字,其修饰的函数和全局变量只在本文件中可见,这样就不会和其他文件冲突了,也就是在.cpp中加载(STB_IMAGE_IMPLEMENTATION)时,预先定义 STB_IMAGE_STATIC ,稍微查看源码即可直到,添加该宏定义以后,函数会被static修改(否则为extern),完美的解决了重定义的问题。推荐大家使用。但是编译阶段可能会有比较多的warning(defined but not used),不过不影响编译。

  2. 如果在其他的子库中(通常是其他人维护的代码)依旧展开了stbi_image.h的定义部分,那么如果你也在你的.cpp中按照正常方式

1
2
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

在最后链接可执行文件的时候就会出现多重定义问题。

这个时候的解决办法是:你只在你的头文件中直接包含stbi_image.h 这样stbi_image的定义部分只被展开了一次,不会出现重定义的问题。