使用GCC编译带有一个C函数的C++代码

3
使用 GCC,我想在一个 .cpp 程序中调用一个声明在 .c 文件中的 C 函数。我使用的命令是: gcc {.cpp文件} -lstdc++ {.c文件} 我不能简单地将 C 文件转换为 CPP,但如果我包含一个共同的头文件,自然会出现以下两种情况之一:
1. CPP 文件无法理解 C 头文件。 2. C 文件无法理解 CPP 头文件。
我该如何处理?我能不能在使用之前编译 C 函数?

3
声明:我不懂C++。为了防止C++编译器对C函数进行名称重整,将C函数的声明封装在extern "C"块中。可能类似于 extern "C" { #include <header.c> } - pmg
首先,.h文件通常用于公开接口。这些接口实际上是一组符号(名称/签名)。C和C++使用不同的机制来唯一生成符号,主要是C++对符号进行了名称修饰,所以两者不能相互理解。正如@pmg所提到的,您需要告诉C++该方法来自C,以便它将使用正确的C符号,我认为您还需要以不同的方式在C中导出要使用的C++符号。参考:https://isocpp.org/wiki/faq/mixing-c-and-cpp - Rob
g++ 工具链驱动程序可以编译 C 文件,并用于将 C 文件链接到 C++ 代码。 - Eljay
2个回答

0
为了解决这个问题,必须先了解C和C++语言是如何编译的。我不会在这里尝试解释它,其他人已经做得比我好得多。因此,我只会提到相关部分。
C或C++头文件没有什么特别之处,#include只是简单地粘贴文件内容(递归)。
每个翻译单元(~一个.c{pp}文件和所有包含的头文件)都被单独编译成一个包含符号表和(几乎)已编译代码的目标文件。
导致问题的可能是头文件中的C或C++特定代码(两种语言都不是另一种语言的超集),或者像@pmg指出的那样的C++符号重整 - 这是最有可能的原因。前者无法解决。后者可以使用extern "C"来解决。

foo.h

void foo(void);

foo.c

#include "foo.h"

#include <stdio.h>

void foo(void){
    printf("Hello from C\n");
}

运行 gcc -c foo.c 将创建包含函数符号 foo 实现的 foo.o

main.cpp

extern "C"{
#include "foo.h"
}
int main(){
   foo();
}

同样地,g++ -c main.cpp会创建main.o目标文件。

然后,运行g++ -o program.out main.o foo.o将它们链接在一起成为可执行的program.out

> ./program.out
Hello from C

extern "C"{} 禁用符号重整,因为包含的代码只是粘贴在那里,所以它适用于整个文件。因此,main.o 函数符号表表示它寻找 foo 函数符号,而不是 _Z3foov 或类似的内容。


0
这是因为C++允许方法重载。为了实现这一点,编译器会标记方法名称以指示可以传递的参数类型(所谓的“名称修饰”)。
如评论中所述,您需要在调用C的任何C++方法中使用extern C声明。为了让C调用C++,您需要在C++源代码中添加一个extern C方法,以便从C中调用它。明白了吗?
相应地构建您的头文件,以便可以从C和C++源文件中包含它:
#ifdef __cplusplus
    extern "C" {
#endif

... // body of header

#ifdef __cplusplus
    } // closing brace for extern "C"

#endif

更多信息请参见: https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html

and https://www.geeksforgeeks.org/extern-c-in-c/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接