在C中调用C++函数会导致致命错误。

13 浏览
0 Comments

在C中调用C++函数会导致致命错误。

我可能没有理解C和C++之间的区别,但是什么时候以及为什么我们需要使用extern "C" { 呢?显然这是一种"链接约定"。

我简单地阅读了一下相关资料,并注意到所有与MSVS一起包含的.h头文件都使用这个标记括起来。什么样的代码被称为"C代码"而不是"C++代码"呢?我以为C++包括了所有的C代码?

我猜测这并不是这样,C++是不同的,标准的特性/函数存在于其中一个而不是两者(例如:printf是C的,cout是C++的),但通过extern "C"声明,C++是向后兼容的。这样说对吗?

我的下一个问题取决于第一个问题的答案,但我还是会在这里提问:既然在C++编译器中,由MSVS编写的C语言头文件都被extern "C" { ... }括起来,那么在自己的代码中何时会需要使用这个呢?如果你的代码是C代码,并且你试图在C++编译器中编译它,不应该没有问题,因为你包含的所有标准头文件已经在它们中使用了extern "C"吗?

在C++编译但链接到已构建的C库时,需要使用这个吗?

0
0 Comments

调用C++函数时在C中出现致命错误的原因是C++编译器对其符号表中的名称的处理方式与C编译器不同。在构建符号表时,需要使用extern "C"声明来告诉C++编译器使用C的名称处理方式。

解决方法是在C++函数声明之前添加extern "C"声明,以告知编译器使用C的名称处理方式。这样可以确保C代码正确地调用C++函数,避免出现致命错误。

示例代码如下:

// C++函数声明
extern "C" {
    void myCppFunction();
}
// C函数调用C++函数
void myCFunction() {
    myCppFunction();
}

通过在C++函数声明前添加extern "C"声明,我们可以在C中正确地调用C++函数,避免出现致命错误。这样,我们可以在C和C++之间实现函数的互相调用和交互。

0
0 Comments

在C和C++项目中调用C函数的标准方法如下:

//
// C_library.h
//
#ifdef __cplusplus
extern "C" {
#endif
//
// ... C_library的函数原型放在这里 ...
//
#ifdef __cplusplus
}
#endif

//
// C_library.c
//
#include "C_library.h"
//
// ... C_library的函数实现放在这里 ...
//

//
// C++_code.cpp
//
#include "C_library.h"
#include "C++_code.h"
//
// ... C++_code的实现可能会调用C_library.c中的C函数 ...
//

注意:上述方法同样适用于从Objective-C++中调用C代码。

C和C++的标准调用约定是一样的,但是还有一些非标准的扩展,比如`far`和`pascal`。

0
0 Comments

在C++中,当声明一个在C中实现/编译的函数时,需要使用extern "C"。使用extern "C"告诉编译器/链接器使用C的命名和调用约定,而不是使用C++的名称重载和调用约定。对于其他库提供的函数,几乎不需要使用extern "C",因为良好编写的库会在公共API中为C和C++导出的函数中包含这个。然而,如果你编写一个既要在C中使用又要在C++中使用的库,那么你就必须在头文件中进行条件性的声明。

关于C代码是否都是C++代码...不,这是一个流行的错误观点,即C++是C的"超集"。虽然C++确实努力保持与C的兼容性,但存在一些不兼容性。例如,bool在C++中是有效的,但在C中是无效的,而_Bool在C99中存在,但在C++中不可用。

至于在系统的".h"文件中是否需要使用extern "C"...任何设计良好的实现都会为你提供这些功能,因此你不需要使用它们。然而,为了确保它们被提供,你应该包含以"c"开头且省略了".h"的等效头文件。例如,如果你包含<ctype.h>,几乎任何合理的系统都会添加extern "C";然而,为了确保使用C++兼容的头文件,你应该包含头文件<cctype>。

你可能还对来自C++ FAQ Lite的混合使用C和C++感兴趣。

谢谢大家的回复。所以,只有在包含已经在C编译器中编译的代码时才需要使用这个吗?

是的,假设你是从C++中包含它,并假设该头文件尚未使用extern "C"。

啊,所以这就是为什么在C++中调用C函数会出现链接和符号错误的原因...

0