c++ - 为什么我可以在库中使用 C++ 代码并从 C 程序调用。这是如何运作的?

标签 c++ c static-libraries calling-convention

我使用 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/

相关文章:

c++ - 链接到可执行文件时如何强制将目标文件包含在静态库中?

c++ - 下标需要数组或指针 ERROR

c++ - 有符号 C++ 整数的非负范围是否至少与负范围一样大?

复制一个 3 dim 数组本身

C block 作用域函数?

c - 链接静态库时获取 undefined reference

c - 它是可移植的编译库吗?

c++ - 多个级别的基类是否会减慢 C++ 中的类/结构?

c++ - 类型 'int*' 和 'int*' 到二进制 'operator+' 的无效操作数

c - 缩进 : space after function name in definition