C&C++混合編程
首先,混合編程不是指在同一個文件裏寫C與C++。
混合編程包括:1,C++引用C的頭文件;2,g++生成的.o與gcc生成的.o相鏈接。
一、extern“C”的作用(最重點)
1. extern "C"的真實目的是實現類C和C++的混合編程。extern “C”是由C++提供的一個連接交換指定符號,用於告訴C++這段代碼是C函數。extern “C”後麵的函數不使用的C++的名字修飾,而是用C。這是因為C++編譯後庫中函數名會變得很長,與C生成的不一致,造成C++不能直接調用C函數。
2.C++語言支持函數重載,C語言不支持函數重載。函數被C++編譯後在庫中的名字與C語言的不同。假設某個函數的原型為:void foo(int x, int y);該函數被C編譯器編譯後在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。C++提供了C連接交換指定符號extern“C”來解決名字匹配問題。
3.被extern "C"限定的函數或變量是extern類型的;extern是C/C++語言中表明函數和全局變量作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變量可以在本模塊或其它模塊中使用。被extern "C"修飾的變量和函數是按照C語言方式編譯和連接的。
4.與extern對應的關鍵字是static,被它修飾的全局變量和函數隻能在本模塊中使用。因此,一個函數或變量隻可能被本模塊使用時,其不可能被extern “C”修飾。
二、extern“C”與__cplusplus
#ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif
_cplusplus標示符用來判斷程序是用c還是c++編譯程序編譯的。當編譯c++程序時,這個標示符會被定義,編譯c程序時,不會定義。於C++文檔的頭文件中,上麵代碼的意思是:如果是C++文件(*.cpp)後綴,則使用extern “C”,在C++項目中應用的非常廣泛。
三、C調用C++函數(接口)
1. cpp頭文件:animal.h
#ifndef __ANIMAL_H__ //防止被重複包含 #define __ANIMAL_H__ class ANIMAL{ public: ANIMAL(char* ); ~ANIMAL(); char* getname(void); private: char* name; }; #endif // __ANIMAL_H__
2. cpp文件:animal.cpp
#include "animal.h" #include <iostream> #include <string.h> using namespace std; ANIMAL::ANIMAL(char* data)//構造函數 { name = new char[64]; strcpy(name, data); } ANIMAL::~ANIMAL() //析構函數 { if(name) { delete[] name; name = NULL; } } char* ANIMAL::getname(void) { return name; }
3. 中間層cpp頭文件:middle.h
#ifndef __MIDDLE_H__ #define __MIDDLE_H__ #ifdef __cplusplus extern "C" { #endif void print(void); #ifdef __cplusplus } #endif #endif
注:middle.h需要包含在.C文件中,因此middle.h中不能包含含有C++關鍵字(如class)的animal.h.
4. 中間層cpp文件:middle.cpp
#include "middle.h" #include "animal.h" #include <iostream> using namespace std; void print(void) //對外接口 { ANIMAL animal("dog"); char* animal_name = animal.getname(); cout << "animal name is :" << animal_name << endl; }
注:接口函數需要用到C++中的class,因此需要包含animal.h.
5. C文件:test.c
#include "middle.h" int main(int argc, char *argv[]) { print(); return 0; }
6. Makefile
main: test.o animal.o middle.o
gcc -o test middle.o animal.o test.o -lstdc++
animal.o:animal.h
g++ -c animal.cpp
middle.o:middle.h
g++ -c middle.cpp
clean:
rm -f middle.o animal.o test test.o
說明:
(1) 在.C文件中包含的直接或間接頭文件中不要有c++關鍵字,因為.C文件是c編譯器編譯的,無法識別C++關鍵字。
(2) .c文件要想使用cpp中的class,需要在一個非成員函數中,而這個非成員函數是在cpp文件中實現的(.c文件不識別class)。
(3) gcc連接時需要加上-lstdc++(使用c++庫),因為默認會使用c動態庫,而c庫中沒有c++的一些函數。
整個上述例子的關係可用圖形表示為:
綠色:必須用c++編譯,要麼是cpp文件,要麼含有class關鍵字
藍色:c文件
橙色:中間銜接頭文件(與c++無關)
注:C調用C++還有一種包裹函數法。
測試:
四、C++調用C函數
應該這個比較簡單,我就不多寫了,就直接寫代碼。
共有三個文件:1.h 1.c main.cpp
[root@localhost aa]#cat 1.h
#ifndef _1__H_
#define _1__H_
extern void print(char* );
#endif
[root@localhost aa]#cat 1.c
#include <stdio.h>
#include "1.h"
void print(char* data)
{
printf("%s\n", data);
}
[root@localhost aa]#cat main.cpp
extern "C"{
#include "1.h"}
int main(void)
{
print(“hello,world\n”);
return 0;
}
gcc –c 1.c
g++ main.cpp 1.o
接著./a.out,又可以出現我們神奇的hello,world了,C++調用C代碼很簡單。
最後更新:2017-04-03 12:56:09
上一篇:
ListView異步加載優化
下一篇:
ListView異步加載優化
Nature:新發現7個臨近的類地行星,十年內可研究其生命跡象
Check Mysql Status
如何使用阿裏雲虛擬主機搭建博客(四)終結篇
iPhone7破解鎖屏密碼_iPhone7ID密碼忘記怎麼辦
CMU計算機學院院長、穀歌工程VP:未來五年看好AI理解情緒和情感
微軟公司第一次全國大筆試將在10月12日進行!
Google 閱讀器鍵盤快捷鍵
ubuntu安裝phpmyadmin
平台之戰,開放終將戰勝封閉
mysql報錯 Access denied for user 'root'@'localhost' (using password: YES)