在GCC环境中开发C和C++混合项目
代码
假设我们有一个用 C++实现的“b 模块”,和 C 语言实现的“a 模块”。我们希望用 a 模块调用 b 模块,也就是 C 调用 C++。
1
2
3
4
5
6
7
8
// b.cpp
#include "b.h"
#include <iostream>
void testfunc(int arg){
std::cout << "testfunc:"<< arg << std::endl;
return;
}
首先我们需要给 b 模块写一个 C 语言能够识别的接口,由于 C++中存在命名空间的概念,所以每个函数在编译后的符号名字会有前缀用以表明命名空间,和 C 中的定义不同,此时 C 将无法通过函数名找到对应的符号。可以通过extern "C"
的方式将其声明为兼容 C 的接口:
1
2
3
4
5
6
7
8
9
10
// b.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void testfunc(int arg);
#ifdef __cplusplus
}
#endif
另一种写法:
1
2
3
4
5
6
7
8
9
// b.h
#pragma once
#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN extern
#endif
EXTERN void testfunc(int arg);
之后可以在 a 模块中直接调用该函数:
1
2
3
4
5
6
7
8
// a.c
#include "b.h"
int main(int argc, char *argv[])
{
testfunc(3);
return 0;
}
使用 C++ 调用 C 语言模块也是同理。
编译链接
1
2
3
PS /> g++ -c b.cpp
PS /> gcc -c a.c
PS /> g++ a.o b.o -o test.exe
使用 g++ 编译 cpp,用 gcc 编译 c,得到中间文件,之后必须要使用 g++ 作为链接器完成链接。
如果使用 cmake 这个过程会更加简单,cmake 会根据文件的后缀名自动选择使用 gcc 还是 g++ 编译,链接时也会自动识别项目中是否包含 c++ ,从而自动选中 g++ 或 gcc 作为链接器:
1
2
3
4
5
6
7
8
cmake_minimum_required(VERSION 3.18)
project(test)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_CXX_COMPILER g++)
add_executable(test a.c b.cpp)
1
2
3
PS /> cd build
PS /> cmake -G "Unix Makefiles" ..
PS /> make
执行结果
1
2
PS /> .\test.exe
testfunc:3
可以看到 C++ 函数被正常调用,且参数传递也正确。
本文由作者按照 CC BY 4.0 进行授权