我的项目用例如下:
- 带有几个声明的外部函数的 C 头文件
- 定义了这些函数的 C++ 源文件
- 将 C++ 源代码编译为共享库
- 在 C 源文件中,通过链接 .so 使用 C 头文件中声明的函数
我在做这件事时发现了一些奇怪的事情。事情开始与未命名的命名空间一起工作。
这是我的示例文件:
c_sample.h
:
#include "stddef.h"
extern void hello(void);
extern void bye(void);
cpp_sample.cc
:
#include <iostream>
#include "c_sample.h"
extern "C" {
void hello(void) { std::cout << "HI" << std::endl; }
void bye(void) { std::cout << "BYE" << std::endl; }
}
在尝试构建共享库时,我看到了预期的错误,因为c_sample.h
它包含在extern "C"
块之外。
g++ cpp_sample.cc -shared -o libcppsample.so
cpp_sample.cc:5:7: error: declaration of 'hello' has a different language linkage
5 | void hello() { std::cout << "HI" << std::endl;}
| ^
./c_sample.h:3:13: note: previous declaration is here
3 | extern void hello();
| ^
cpp_sample.cc:6:7: error: declaration of 'bye' has a different language linkage
6 | void bye() { std::cout << "BYE" << std::endl;}
| ^
./c_sample.h:4:13: note: previous declaration is here
4 | extern void bye();
| ^
2 errors generated.
然而,当我把它包装在一个未命名的命名空间中时,奇迹发生了
cpp_sample.cc
:
#include <iostream>
#include "c_sample.h"
extern "C" {
namespace {
void hello(void) { std::cout << "HI" << std::endl; }
void bye(void) { std::cout << "BYE" << std::endl; }
}
}
编译成功了。当我尝试从另一个 C 源文件中使用它时,它甚至可以工作。
#include "stdio.h"
#include "c_sample.h"
int main() {
hello();
}
$ gcc another.c -L/tmp -lcppsample -o another
$ ./another
HI
仅将其包装在命名空间内如何工作?它如何将声明的函数与其定义链接起来?