C和C++的混合編程及庫的調用

1·如何混合編程;
(1)程序編譯過程:源文件->目標(庫)文件->可執行程序->鏡像文件
(2)任何編程語言執行時都必須是可執行程序,所以都必須先被編譯成目標文件
(3)混合編程的“混合”操作發生在鏈接這一步

2;C++和C混合編程的困難所在
(1)C++和C都是編譯型語言,互相混合相對容易
(2)難點:C++支持函數名重載,而C不支持,因此編譯器生成目標文件時,函數名在目標文件中的臨時內部名稱規則不同。導致鏈接時符號對不上
(3)解決方案:使用extern “C”{}; 讓C++在對接的局部向C妥協兼容

3;實驗驗證extern 的效果;
(1)預備知識;
gcc clib.c -c -o clib.o 編譯可執行程序
g++ -E clib.c -o clib.i 只進行預處理展開生產clib,i文件
objdump -d clib,o > clib.i 反編譯將可執行程序逆向出彙編語言
C和C++中的函數在編譯後都會在符號表裏面用一個符號表示,也就是名稱。

實驗一;編譯反編譯;證明了C語言中名稱爲add的函數,編譯後符號表中就叫add
在這裏插入圖片描述
實驗二;證明了C++語言中名稱爲add的函數,編譯後符號表中叫_Z3addii;並且其重載機制的命名

在這裏插入圖片描述
分析:同樣的源碼,編譯後生成的二進制代碼其實是一樣的,所以功能其實也是一樣的所以本質上是可以混合編程的,但是生成的中間符號名稱不同,所以鏈接器難受。

實驗三:證明了在C++的頭文件中,只要把C++的函數的聲明放在extern “C”{}的大括號範圍之內,就可以讓g++在編譯這個函數時生成中間符號名時按照C的規則而不是按照C++的規則,所以這樣的函數就可以和C的庫進行共同鏈接。
在這裏插入圖片描述

4;C和C++庫調用
三種情況
(1)同一個項目全部有源碼,一次編譯鏈接。
直接在C的頭文件中加extern "C"聲明,即可。則對應的函數都會使用c方法來生成符號表,從而不會衝突。
(2)同一個項目中C是庫,C++是源碼,C++調用C
在C的頭文件中加extern "C"聲明,在C++中直接包含頭文件調用即可;因爲給庫都是給庫和.h文件的

實踐;
預備知識;
C語言如何編庫;動態鏈接庫的後綴爲.os的,靜態庫的後綴爲.a的
靜態庫;
gcc -c zw.c -o zw.o ;編譯zw.c生成可執行程序zw.o
ar -rc libzw.a zw.o ;根據可執行程序zw.o打包生成zw.a的靜態庫。
gcc test,c -o test.o -lzw.a -L. ;使用靜態庫, -l後面接庫名,-L後接庫的路徑。
nm可以查看.a文件有哪些符號。
在這裏插入圖片描述
(3)同一個項目中C++是庫,C是源碼,C調用C++
需要自己來一層封裝,將帶來的.h文件封裝一下,並且把新的.h文件添加上extern "C"聲明;
(1;用cpp寫一個庫,mylib.cpp mylib.hpp,用g++編譯成靜態庫
(2;objdump反編譯庫,查看確認符號
(3;用cpp寫一個封裝層,用上extern “C”,cmylib.cpp和cmylib.hpp,用g++編譯成靜態庫
(4;objdump反編譯庫,查看確認符號
(5;用c寫一個main.c,調用wrapper庫,用gcc編譯鏈接,運行查看結果
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章