/* 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++函數庫。