【发布时间】:2021-03-23 01:52:17
【问题描述】:
我没有需要解决的问题,但对以下问题感到非常困惑:
我正在使用 CMake(在内部使用 gcc)。不确定这是否重要。
假设我有一个项目,它包含一个 C++ 静态库 LibCpp 和一个演示 C++ 可执行文件 DemoCpp,它链接到并使用 LibCpp。 LibCpp 库是从 C 和 C++ 源代码编译而来的。正确的做法是让 LibCpp 的 C++ 代码文件将所有 C 头文件包含为extern "C" {#include "c_header.h"}。如果这样做了,静态库链接正常,可执行 DemoCpp 成功链接到 LibCpp。一切正常。
假设,我忘了输入extern "C",只是将 C 头文件作为 C++ 头文件包含在内。正如预期的那样,整个项目无法链接。然而,这让我感到困惑,当 DemoCpp 尝试链接到 LibCpp 时,链接失败!我原以为它在链接静态库时已经失败了。但是,静态库(例如LibCpp.a 文件)构建得很好,只是不能使用。
这让我很费解,因为要链接静态库(我认为),链接器必须将引用解析为编译为 C 的代码。我认为这也很烦人,因为我不能依赖库仅在库本身设法被链接后才“可链接到”。我错过了什么吗?
你不需要看下面的代码示例,除非你不明白我的问题或者不相信我说的话。
# CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(LibraryLinkerEvil)
# Toggle this line to see that linking fails for DemoCpp BUT NOT FOR LibCpp!!!
add_compile_definitions(USE_EXTERN_C)
set(CMAKE_CXX_STANDARD 17)
add_library(LibCpp cpp_lib.cpp util.c)
add_executable(DemoCpp main.cpp)
target_link_libraries(DemoCpp PRIVATE LibCpp)
// cpp_lib.cpp
#ifdef USE_EXTERN_C
extern "C" {
#endif
#include "util.h"
#ifdef USE_EXTERN_C
}
#endif
int call_c_function(int a, int b) {
return add(a,b);
}
// main.cpp
#include <iostream>
int call_c_function(int a, int b); // could be in a separate C++ header.
int main() {
std::cout << "Hello, World! " << call_c_function(2,2) << std::endl;
return 0;
}
// util.h (C header)
#ifndef LIBRARYLINKEREVIL_UTIL_H
#define LIBRARYLINKEREVIL_UTIL_H
int add(int a, int b);
#endif //LIBRARYLINKEREVIL_UTIL_H
// util.c (C source file)
int add(int a, int b) {
return a+b;
}
【问题讨论】:
-
我很惊讶它进入了链接步骤。原因如下:
malloc需要在 C++ 中进行输出转换,但在 C 中不需要。 -
@EvanHendler 我在问题的任何地方都没有看到 malloc
-
这不是评论的重点。我确定
malloc存在于依赖项中。如果不是malloc,那么其他一些函数在 C 和 C++ 之间的语法略有不同。包含 C 代码时应始终使用Extern "C"。 -
@EvanHendler 我认为根据帖子中没有证明的假设发表评论并不是很有用。
-
@EvanHendler 我认为这并不令人惊讶。离开函数
extern "C"只会改变你如何使用它,如果你将它传递给需要extern "C"函数的东西(例如qsort)。如果你不这样做,那么就没有问题。例如,自定义void* mymalloc(size_t)函数在 C++ 中的调用方式相同,无论它是否为extern "C"。
标签: c++ c linker static-libraries