工程实战中的使用技巧——C++和C的相互调用

c/c++

浏览数:181

2019-9-11

AD:资源代下载服务

C++是在C的基础上发展起来的。当我们用C++写项目工程的时候,很有可能以前的许许多多的代码都是用C语言写的。那么,当我们用C++编译程序的时候,之前用C写的代码就放弃不用了吗?当然不可能。如果工程量浩大,直接放弃之前用C写的程序重新用C++写一遍耗时又耗力,更何况C++自诞生以来就有一个重大的使命——兼容C语言。更何况之前用C写的代码是经过检验的可以使用的代码,难道就能因为现在用C++来写工程,之前写的完全可以运行的大量C代码就不用了吗?很显然,不肯能吧。
那么,有人就会感到疑惑了。C++ 既然天生就是能够兼容C语言的,那么用C++编译器编译C语言完全是可以通过的啊。难道不对吗?对的,完全正确。如果是源码,那么C++编译器完全可以通过运行。但是,如果一段程序是用C写的,这段代码已经被编译成了目标文件,那么还能再用C++编译通过吗?显然,已经不行了。关于这点的实际使用就是,我们在C++程序里面会用到一些第三方的库,而这些库是用C语言编写并编译的。
所以,我们在实际工程中,必须得让C++代码能够使用C语言编写的库。
接下来,我们用一个简单的例子来说明,我们上面阐述的内容。
首先,我们先来写一个简单的函数,该函数在add.c这个文件中实现。这个函数实现相加功能(喂喂喂,怎么写这么简单的一个函数啊?说明原理用不着举一个很深奥的例子吧,啊哈哈哈)

int add ( int a, int b ){

    return a + b;
}

接下来,我们再写一个头文件,用来声明我们所写的函数。

int add ( int a, int b );

然后,我们可以经过编译生成一个目标文件。

这个add.o文件就是我们编译后生成的。

然后,我们要开始编写主程序。

int main ( int argc, char** argv ){

    printf ( "sum = %d\n", add ( 2, 3 ) );

    system ( "pause" );
    return 0;
}

这段主程序被保存在main.cpp这个文件中。接下来,我们来编译运行程序。

编译后,我们发现,程序报错了。错误信息提示说,我们没有声明这个函数,可是我们明明声明了呀,这是为什么呢?我们可以先来查看一下,add.o文件中到底有没有add函数。

经过查看后,我们发现,add.o中确实是有add函数的啊。
那么,很明显,由于我们上面的操作,这个add.o文件是用C语言编译器编译出来的。而这个main.cpp是用C++编译器编译。所以,我们直接想用C++编译器使用C编写的目标代码就会报错。
假如我们在实际工程中,有大量的第三方库都是用C编写的,而我们用的确实c++语言,编译器也是用的C++编译器,那这个用C语言写的第三方库我们就不用了吗?当然不是,肯定会有解决方案。怎么解决呢?
extern关键字能强制让C++编译器进行C方式的编译。
那么,我们在C++文件中,加上这么段代码,就可以告诉编译器,其中的C代码要用C方式编译。

extern "C"
{
    #include "add.h"
}

这样以来,我们就告诉编译器,我们用extern包含的头文件中的代码是C代码,我们要用C编译器来编译它。
下面上main.cpp中的完整代码:

#include <stdio.h>
#include <stdlib.h>

extern "C"
{
    #include "add.h"
}
int main ( int argc, char** argv ){

    printf ( "sum = %d\n", add ( 2, 3 ) );

    system ( "pause" );
    return 0;
}

然后,我们再来编译一下。

运行之后,我们发现,编译通过,并且运行结果正确。
由上面这个例子,我们又引出一个问题:我们如何保证一段代码始终以C的方式被编译。可能有部分大佬觉得,刚刚不是才学过吗,用extern。那么不好意思大佬,我得告诉你,extern在C++中才支持,在C中就不支持了。
不信的话,大佬们,我们一起来实验一下。首先,我们来定义一个main.c文件。

#include <stdio.h>
#include <stdlib.h>

extern "C"
{
    #include "add.h"
}
int main ( int argc, char** argv ){

    printf ( "sum = %d\n", add ( 2, 3 ) );

    system ( "pause" );
    return 0;
}

运行之后,我们发现,

程序报错了。
上面这段不符合C的规则,因为extern可是C++的写法。(大佬们这下应该相信小生说的话了吧)
那么,我们怎么做才能保证这段代码既能被C++编译过又能被C编译过?解决方案当然是有的啦。如果没有,我就不在这里吹牛B了,啊哈哈哈。怎么做呢?
通过使用C++编译器内置的一个标准宏_cplusplus。通过这个标准宏我们可以判断该编译器是否是C++编译器。
接下来,我们来实际使用一下:

#ifdef _cplusplus
extern "c" {
#endif
#include "add.h"
#ifdef _cplusplus
}
#endif

我们只要将这段代码加到main.c文件中去就可以了。我们来编译一下:

编译之后,我们发现,编译通过了。问题被完美的解决了。

作者:BarnabyRoss