C静态库调用外部库函数出现PlaySoundA@12未定义引用错误
问题:静态库调用外部函数时出现
undefined reference error to PlaySoundA@12 我开发了一个包含调用外部库函数的C静态库,在构建测试应用时触发undefined reference error to PlaySoundA@12错误,开发流程如下:
步骤1:含外部引用的函数实现
audio_functions.c文件内容:
#include <windows.h> #include <Mmsystem.h> //For PlaySound() - Winmm.lib is library #include "audio_functions.h" uint8_t play_sound(const char *path) { int psret; psret = PlaySound(path, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT | SND_NOSTOP); if(psret) { return 1; } else { return 0; } }
该函数用于测试静态库调用外部库的场景。
步骤2:构建静态库
通过bat脚本构建库:
set pname=_ERZ_LIBRARY set location=C:\MinGW\bin\proj\%pname% //Creating .o files //only in audio_functions is an external referance, the other functions works gcc -c -pedantic %location%\audio_functions\*.c -o %location%\_AR\audio_functions.o ... more files cd %location%\_AR\ //Use ar.exe to create archiv from all .o files where created ar -rcs %location%\BUILD\ERZ_LIBRARY.lib *.o //Take a look to all functions in library nm --print-armap %location%\BUILD\ERZ_LIBRARY.lib
nm命令输出显示库中包含_play_sound,且存在未定义的_PlaySoundA@12引用。
步骤3:使用静态库
测试文件test_erz_library.c内容:
#include <windows.h> #include <conio.h> #include <stdio.h> #include <inttypes.h> #include <string.h> #include <stdlib.h> #include <mmsystem.h> #include "C:/MinGW/bin/proj/_ERZ_LIBRARY/ERZ_LIBRARY.h" int main() { output(blue, NULL, "TEST -- [Version %s]", "1.0.0"); //function from ERZ_LIBRARY that works get_version(1); //function from ERZ_LIBRARY that works play_sound("C:\\MinGW\\bin\\proj\\test_erz_library\\Aramam.wav"); //function from ERZ_LIBRARY that do not work and printing the undefined reference error }
编译脚本:
set val=test_erz_library set pname=test_erz_library gcc C:\MinGW\bin\proj\%pname%\%val%.c -lWinmm -LC:\MinGW\bin\proj\_ERZ_LIBRARY\BUILD -l:ERZ_LIBRARY.lib -o C:\MinGW\bin\proj\%pname%\%val%.exe C:\MinGW\bin\proj\%pname%\%val%.exe
去除play_sound调用后,其他库函数可正常工作,调用该函数则触发上述错误。
问题原因
GCC链接器遵循依赖库必须放在被依赖的目标文件/库之后的规则。当前编译命令中,-lWinmm放在了测试源文件和静态库之前:链接器处理Winmm.lib时,还未发现需要它的play_sound函数,会直接跳过该库;后续处理ERZ_LIBRARY.lib中的play_sound时,需要PlaySoundA@12,但已无法回溯到之前的Winmm.lib,因此报未定义引用错误。
解决方案
调整编译命令中库的顺序,将-lWinmm移到静态库之后:
set val=test_erz_library set pname=test_erz_library gcc C:\MinGW\bin\proj\%pname%\%val%.c -LC:\MinGW\bin\proj\_ERZ_LIBRARY\BUILD -l:ERZ_LIBRARY.lib -lWinmm -o C:\MinGW\bin\proj\%pname%\%val%.exe C:\MinGW\bin\proj\%pname%\%val%.exe
补充说明
- 静态库仅保存未定义的外部引用,构建静态库时无需链接
Winmm.lib,你的静态库构建流程是正确的。 - 确认
Winmm.lib位于MinGW默认库路径(通常为C:\MinGW\lib),若不在,需额外添加-L<Winmm所在路径>参数。
内容的提问来源于stack exchange,提问作者Erz
相关产品推荐
相关产品推荐

