编译器:mingw64
1. 配置 c_cpp_properties.json
实现 vscode 对 ffmpeg 库的代码提示功能
按下 ctrl + shift + p,输入 c/c++,选择:
添加 ffmpeg 的 include 路径,使 vscode 能够获取库函数的代码提示
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"E:\\ProgramLibs\\ffmpeg\\ffmpeg-7.1\\include"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"compilerPath": "D:\\Soft\\MinGW\\mingw64\\bin\\gcc.exe",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}
2. 配置 task.json
配置 task.json 来实现链接 ffmpeg 库编译我们的代码
在打开任意 c/c++ 文件的 vscode 页面中,按下 ctrl + shift + p,输入 tasks,选择
在编译命令的参数中加入 ffmpeg 的库目录、包含目录,以及要链接的库(我这里使用的是静态库,如果使用动态库,还需要将库目录中的 .dll 文件拷贝到 生成的可执行文件 的目录下,才能正确运行可执行文件。不拷贝也能正常编译,但是却无法运行编译出来的可执行程序)
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe 生成ffmpeg活动文件",
"command": "D:\\Soft\\MinGW\\mingw64\\bin\\gcc.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-L",
"E:\\ProgramLibs\\ffmpeg\\ffmpeg-7.1\\lib",
"-I",
"E:\\ProgramLibs\\ffmpeg\\ffmpeg-7.1\\include",
"-lavcodec",
"-lavdevice",
"-lavfilter",
"-lavformat",
"-lavutil",
"-lpostproc",
"-lswresample",
"-lswscale",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "编译器: D:\\Soft\\MinGW\\mingw64\\bin\\gcc.exe"
}
]
}
3. 配置 launch.json
配置调试相关的设置
点击顶部栏中的 `运行`,选择 `添加配置`
在 launch.json 中的 configurations 中添加 `(gdb) 启动` 配置
配置运行程序和调试器的路径:
(同样地,如果使用动态库,还需要将库目录中的 .dll 文件拷贝到 生成的可执行文件 的目录下,才能保证 gdb 调试 的时候可以运行 .exe 文件)
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "D:\\Soft\\MinGW\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
4. cpp 文件下使用 FFmpeg 库的注意事项
FFmpeg 库同样可以用于 C++ 开发,值得注意的是,由于 FFmpeg 库是使用 C 语言编写的,因此我们在引用其头文件时,应该使用 extern "C" 进行修饰,原因如下:
- 背景知识:C++ 与 C 语言的链接方式差异
- 在 C++ 中,函数重载是一个重要的特性。这意味着可以有多个同名函数,只要它们的参数列表不同。为了实现函数重载,C++ 编译器会对函数名进行名称修饰(Name Mangling)。例如,一个简单的 C++ 函数
int add(int a, int b)
在编译后的符号名可能会被修饰成类似_Z3addii
这样复杂的名字(不同编译器的修饰规则不同),其中Z
表示这是一个 C++ 函数,3add
表示函数名是add
,ii
表示函数有两个int
型参数。- 而 C 语言没有函数重载的概念,函数名在编译后的符号名就是其本身。例如,一个 C 函数
int add(int a, int b)
在编译后的符号名就是add
。extern "C"
的作用
- 当在 C++ 代码中需要调用 C 语言编写的函数或者使用 C 语言编写的库时,就会用到
extern "C"
。extern "C"
的主要作用是告诉 C++ 编译器,被它包围的代码应该按照 C 语言的方式进行链接,即不进行函数名修饰。- 例如,如果有一个 C 语言编写的库,里面有一个函数
int add(int a, int b)
,当在 C++ 代码中想要调用这个函数时,如果直接包含头文件并调用,C++ 编译器会按照 C++ 的方式去寻找经过名称修饰后的函数符号,这样就会找不到正确的函数。
简单代码如下:
#include <bits/stdc++.h>
extern "C"
{
#include <libavutil/log.h>
}
int main(int argc, char const *argv[])
{
av_log_set_level(AV_LOG_DEBUG);
std::cout << "hello world" << std::endl;
av_log(NULL, AV_LOG_INFO, "hello FFmpeg!\n");
return 0;
}
同时,我们也可以将 c_cpp_properties.json 和 task.json 中配置的编译器修改为 g++ 进行编译