我使用 Visual Studio 2008 使用以下两个文件在 Windows 上创建了一个静态库:
头文件是一个简单的 C API:
#ifdef __cplusplus
extern "C" {
#endif
void init();
void stop();
#ifdef __cplusplus
}
#endif
然而,实现是使用 C++ 功能:
#include "my_lib_api.h"
#include <iostream>
void init() {
std::cout << "Initializing my_lib\n";
}
void stop() {
std::cout << "stopping my_lib\n";
}
然后我使用这些命令进行构建:
mkdir Release
cl.exe /O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_LIB" /FD /EHsc /MT /Gy /Fo"Release\\" /W3 /c /Zi /TP my_lib_api.cpp /nologo /errorReport:prompt
lib.exe /OUT:my_lib_api.lib /LTCG .\Release\my_lib_api.obj /NOLOGO
然后,我将 my_lib_api.lib 和 my_lib_api.h 复制到一个新文件夹,在其中使用 main.c 源文件创建了一个新的 Visual Studio 控制台应用程序:
#include "my_lib_api.h"
int main(int argc, char* argv[]) {
init();
stop();
return 0;
}
我使用相同的/MT 多线程 C 运行时库构建,以与库保持一致。然后它的构建如下:
mkdir Release
cl.exe /O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FD /EHsc /MT /Gy /Fo"Release\\" /W3 /c /Zi /TC .\main.c /nologo /errorReport:prompt
成功创建Release/main.obj
link.exe /OUT:c_api_so.exe /INCREMENTAL:NO /MANIFEST:NO /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /LTCG /DYNAMICBASE /NXCOMPAT /MACHINE:X86 my_lib_api.lib kernel32.lib user32.lib shell32.lib .\Release\main.obj /NOLOGO /ERRORREPORT:PROMPT
成功创建c_api_so.exe,运行良好。
这意味着我可以用 C++ 编写一个库,只要我提供 C API,那么 C 和 C++ 调用程序都可以使用我的库?这是普遍正确的吗?这应该总是有效吗?为什么它有效?我假设对于每个平台,您会说只支持一个编译器/链接器,并在 Windows 上提供基于 Visual Studio 的库,在 Linux 上提供基于 GNU C 的库?有什么需要注意的问题吗?
最佳答案
从广义上讲,函数就是一个接口(interface)。调用者所关心的是它是否满足该接口(interface)。实现完全无关。在本例中,通过使用 extern "C",您告诉 C++ 编译器创建一个 C 编译器可以使用的二进制接口(interface),它确实做到了。接口(interface)是匹配的(由标准保证),因此您可以非常安全地从 C 调用它。需要重申的是,主体在这里完全不重要,并且可以用任何语言实现。 许多语言都提供了定义可从 C 调用的函数的功能。
更具体地说,C ABI(此处 ABI 是二进制接口(interface)的名称)并未由标准指定,但实际上所有操作系统都定义了该平台上的每个人都使用的 C ABI。这是 C 仍然是编程的“通用语言”的主要原因——实际上每个人都可以在二进制级别上使用 C。
关于c++ - 为什么我可以在库中使用 C++ 代码并从 C 程序调用。这是如何运作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25584098/