最近在看人工智能相关的知识,无意中发现了一个巨牛的 人工智能教程,分享一下给大家。
教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点 这里 可以直接看教程。
简介
C++ 中调用 C 比较简单. 但是 C 调用 C++ 稍微复杂一些.
C 调用 C++ 分为可以调用 C++ 类中的函数和普通 cpp 中的函数. 无论是哪种函数, 我们都可以使用封装了 C++ 的文件作为适配供给 C 来使用.
下面看具体的例子.
C++ 调用 C
首先创建 CFile.h 和 CFile.c 文件.
CFile.h
1 | #ifndef CFile_h |
CFile.c
1 | #include "CFile.h" |
在 C++ 文件中调用 C 代码, 示例如下:
main.cpp
1 | extern "C" { |
这里可以看到导入 C 文件的方式:
1 | extern "C" { |
如果直接导入, 如:
1 | #include "CFile.h" |
编译报错:
1 | Undefined symbols for architecture x86_64: |
这里的 extern "C"
告诉编译器, 要按照 C 的链接约定,而不是 C++ 的链接约定.
C 编译器不支持 extern "C"
.
C 调用普通 C++ 的函数
C 调用 C++ 有点曲折.
CPPFile.hpp
1 | #ifndef CPPFile_hpp |
CPPFile.cpp
1 | #include "CPPFile.hpp" |
这里需要写一个中间的 cpp(CPPAdapter.cpp)文件, 提供方法给 C 来使用.
注意: 这里没有 CPPAdapter.hpp
头文件.
CPPAdapter.cpp
1 | #include "CPPFile.hpp" |
然后在 C 中调用 C++ 的代码:
CFile.c
1 | #include "CFile.h" |
C 调用 C++ 类中的方法
和上面例子的原理一样的.
CPPClassFile.hpp
1 | #ifndef CPPClassFile_hpp |
CPPClassFile.cpp
1 | #include "CPPClassFile.hpp" |
CPPAdapter.cpp
1 | #include "CPPFile.hpp" |
在 C 中可以调用了, 如下代码:
CFile.c
1 | #include "CFile.h" |
extern “C”
extern "C"
中的 “C” 并不表示 C 语言,”C” 表示的是一种链接约定.
extern "C"
指令描述的是一种链接约定,它并不影响调用函数的定义,即使做了该声明,对函数类型的检查和参数转换仍要遵循 C++ 的标准,而不是 C 的标准.
不同的编程语言(编译型)链接特性是不同的,这也决定了它们编译后的链接符号的不同.
如函数 void function(int d)
,C 语言会把它编译成类似 _function
这样的符号,C 链接器只要找到该函数符号就可以链接成功.
C++ 会把这个函数编译成类似 _function_int
或 _xxx_functionIntxxx
这样的符号,即在符号上增加了类型信息,这也解释了为什么 C++ 可以实现函数重载了.
那么,对于用 C 编译器编译成的库,用 C++ 直接链接势必会出现不能识别符号的问题,用 extern "C"
就可以解决, 正如上面的例子.
简单来说, extern "C"
的作用就是让编译器知道要以 C 语言的方式编译和链接函数.
__cplusplus 宏
__cplusplus
宏是 C++ 编译器默认定义的.
类似如下的代码:
1 | #ifdef __cplusplus |
在 C++ 中, 编译器将 fun 按照 C 的链接约定来编译, 而如果是 C 编译器, 直接按照 C 的链接约定来编译即可.
__cplusplus
是在 C++ 编译器中默认定义的,C语言不支持 extern "C"
.
上面的代码很实用, 也是一种编程技巧.