碼工聲明:本人也在學習,下面有些話是網上摘抄的---吐血的CSDN,圖片不支持拷貝,不支持拷貝爲啥還要正常顯示,導致很多貼圖都沒有了
只介紹c調用c++過程中我所遇到的一些低級錯誤
1.先介紹一下c和c++編譯
如果是已經用c++編譯器編譯好的so文件,使用c語言直接引用是會報錯的,原因是c和c++的編譯器在處理函數名稱時規則不同,相同的函數比如hello(int i),c語言可能會處理成hello或者_hello,具體估計與編譯器有關,但c++的話由於存在重載功能,會將參數類型等信息全部包含進去,一遍唯一定位某一函數,所以c++可能命名爲_Z10helloP9int,這樣即使存在hello函數名稱相同的,但由於參數部分的名字不同,也可以唯一定位到需要的函數。呵呵,c++我不懂,班門弄斧了,囉嗦了一句。
hello.cpp編譯生成libhello.so
相同的函數下面是用c++編譯的結果
“圖片被CSDN吃了”
下面是通過extern "C" 選項編譯的,代碼如圖所示
“圖片被CSDN吃了”
hello.h代碼
“圖片被CSDN吃了”
同樣hello.h中的聲明也要用extern "C",否則會報錯,錯誤如下,應該是相同函數定義規則不同衝突了
“圖片被CSDN吃了”
編譯過後的nm查看函數名如下
“圖片被CSDN吃了”
可以看出函數hello與代碼名稱相同,且不帶參數
2、extern "C",注意c一定要大寫,小寫會報錯;__cplusplus 前面是兩個下劃線
“"C"表示的是一種鏈接約定,只是因C和C++語言之間的密切關係而在它們之間更多的應用而已。實際上Fortran和彙編語言也常常使用,因爲它們也正好符合C實現的約定。
extern "C"指令描述的是一種鏈接約定,它並不影響調用函數的定義,即時做了該聲明,對函數類型的檢查和參數轉換仍要遵循C++的標準,而不是C”
此外還有extern "FORTRAN"
還是以hello word爲例,假設用cpp且不加extern "C"來編譯,那麼生成的libhello.so是按照c++的約定進行編譯的,如果c要調用則必須使用一箇中間的過度,使得編譯生成的函數按照c語言的約定編譯,這樣在調用時才能找到
中間文件定義爲helloInf.cpp,不截圖了,手敲吧
#include "hello.h"
#ifdef __cplusplus
extern "C" {
#endif
void helloInf()
{
hello(1);
}
#ifdef __cplusplus
}
#endif
同理如果helloInf.h裏面的聲明也要加上#ifdef __cplusplus.....
編譯生成的libhelloInf.so,用main.c就可以直接調用了
main.c
#include "helloInf"
void main(void)
{
helloInf();
}