/* procrank.h */
#include <stdio.h>
#ifndef PROCRANK_H
#define PROCRANK_H
#ifdef __cplusplus
extern "C" {
#endif
extern void print_hello();
#ifdef __cplusplus
}
#endif
#endif
#include "procrank.h"
#include <stdio.h>
void print_hello()
{
printf("hello world!\n");
printf("hello world!\n");
}
/* main.cpp */
#include "procrank.h"
int main()
{
print_hello();
return 0;
}
(1)__cplusplus宏干什么的, __cplusplus是cpp中的自定义宏,定义了该宏说明这是一段CPP的代码,所以这里的H文件的含义为:如果此文件用于CPP代码时,就加上exern "c".
(2)C与C++函数汇编时的区别:
int f(void)
{
return 1;
}
在加入extern "C"的时候产生的汇编代码是:
.file "test.cxx"
.text
.align 2
.globl _f
.def _f; .scl 2; .type 32; .endef
_f:
pushl %ebp
movl %esp, %ebp
movl $1, %eax
popl %ebp
ret
但是不加入了extern "C"之后
.file "test.cxx"
.text
.align 2
.globl __Z1fv
.def __Z1fv; .scl 2; .type 32; .endef
__Z1fv:
pushl %ebp
movl %esp, %ebp
movl $1, %eax
popl %ebp
ret
两段汇编代码同样都是使用gcc -S命令产生的,所有的地方都是一样的,唯独是产生的函数名,一个是_f,一个是__Z1fv。
从中,可以看出C与C++代码的不同了,也就是产生中间函数名时的命名机制已经发生了变化,相对来说,C比较简单,而C++则要更规范,更复杂一些。
当我们使用C与C++混编时,或者说用C++代码复用C代码时,就会产生相应的问题,了支持原来的C代码和已经写好C库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。它的实际作用就是,在C++调用C函数库的时候,能够让C++代码正确地找到C函数库中的函数名,最终连接产生对应的C库文件中。
从我们给出的例子,很容易就看出来了,C++调用C库时,是多了一个exern "c".
这里需要注意的是,当我们的H头文件,如果只是纯粹的C文件头,这里是不支持使用extern "c"的.
(3)从上面的第二条,可以看出,这里的extern 确实是为了确存C与C++混编而使用的一种策略,这也是C++的创始人为了兼容部分C代码而设计。
(4)那C调用C++库呢?
/* procrank.h */
#include <stdio.h>
#ifndef PROCRANK_H
#define PROCRANK_H
extern "C" void print_hello();
/* procrank.cpp */
#include "procrank.h"
#include <stdio.h>
void print_hello()
{
printf("hello world!\n");
printf("hello world!\n");
}
/* main.c */
//#include "procrank.h"
extern void print_hello(); //add
int main()
{
print_hello();
return 0;
}
注意,这里使用了exern "c" void print_hello();这里是为了让C代码能够正确地调用C++函数库。