0 約定:c檔案使用gcc編譯,cpp檔案使用g++編譯,生成對應的object檔案
g++也可以編譯c檔案,但是預設編譯出來的符號是以c++方式
我們可以指定extern "c" 或者 extern "c++",來指定編譯的時候函式是以c或者c++方式修飾
使用g++編譯需要嚴格型別檢查,所以對於c檔案,盡量還是用gcc來完成編譯
1 c++呼叫c:c函式宣告需要增加標識 extern "c"
舉例如:
#ifdef __cplusplus
extern "c"
#endif
2 c呼叫c++,則必須在c++的函式外封裝乙個c函式的殼,才能完成簡介呼叫
最後鏈結有兩種方法
a 一種是以gcc鏈結,需要提供乙個動態庫,這個動態庫中混合了c函式和c++方法
b 一種是以g++鏈結,需要提供乙個靜態庫,這個靜態庫中混合了c函式和c++方法
本文以乙個網路地理資訊查詢功能的**為例,詳細講述這兩種方法
c++部分包括logging.h,ip_util.h,ip_geo.h,我們增加乙個c函式的殼:ip_geo_api.h,ip_geo_api.cpp
//通過這樣的技巧,就可以在gcc和g++編譯的時候共用同乙個標頭檔案
#ifdef __cplusplus
#define shared_api extern "c" __attribute((visibility("default")))
#else
#define shared_api
#endif
//extern "c",這是乙個c函式,具體實現在ip_geo_api.cpp,由於呼叫了c++方法,所以要以g++編譯
//而其他c函式可以直接呼叫這個殼函式,用gcc編譯
shared_api void init_ip_geo();
3 下面我們看一下完整的編譯過程
方法a:參考附件ip_geo_using_so.tar.gz
step1:src/makefile
[root@localhost src]$ make
g++ -i./ -o2 -c -std=c++0x -wall -wno-unused-function -fpermissive -g -fpic ip_geo_api.cpp -o ip_geo_api.o
g++ -o2 -shared -fpic -o libip_geo.so ip_geo_api.o #生成動態庫,完成c函式的殼
[root@localhost src]$ make install
mkdir -p ../include
mkdir -p ../lib
mkdir -p ~/lib
cp ip_geo_api.h ../include
cp libip_geo.so ../lib
cp libip_geo.so ~/lib #這一步的目的就是把動態庫放到$ld_library_path下
step2:test/makefile
[root@localhost test]$ make
gcc -i../include -o2 -c -wall -wno-unused-function -fpic -dndebug test.c -o test.o
gcc -o2 -fpic -l../lib -lip_geo -o test test.o #都採用gcc編譯和鏈結
[root@localhost test]$ ldd test
linux-vdso.so.1 => (0x00007fff0ef82000)
libip_geo.so => /root/lib/libip_geo.so (0x00007fefbec60000)
libc.so.6 => /lib64/libc.so.6 (0x000000378b200000)
libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007fefbe956000)
libm.so.6 => /lib64/libm.so.6 (0x0000003adec00000)
libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007fefbe740000)
/lib64/ld-linux-x86-64.so.2 (0x000000378aa00000)
方法b:參考附件ip_geo_using_a.tar.gz
step1:src/makefile
[huaizhi@pprobe75 src]$ make
g++ -i./ -o2 -c -std=c++0x -wall -wno-unused-function -fpermissive -g -fpic ip_geo_api.cpp -o ip_geo_api.o
ar -rv libip_geo.a ip_geo_api.o #生成動態庫,完成c函式的殼
ar -r libip_geo.a ip_geo_api.o
ar: creating libip_geo.a
[huaizhi@pprobe75 src]$ make install
mkdir -p ../include
mkdir -p ../lib
mkdir -p ~/lib
cp ip_geo_api.h ../include
cp libip_geo.a ../lib
cp libip_geo.a ~/lib #只是為了找個地方能夠存放
step2:test/makefile
[huaizhi@pprobe75 test]$ make
g++ -i../include -o2 -c -wall -wno-unused-function -fpic -dndebug test.c -o test.o#也可以用gcc編譯
g++ -o2 -fpic -o test test.o -l../lib -lip_geo -lm #必須要用g++完成鏈結
在本文對c和c++介面部分的資料結構在編碼的時候使用了兩個不同的小技巧,從而可以少寫乙個類似的結構
在ip_geo_using_so.tar.gz這個例子中,struct/class ippair是作為struct ip_geo_info的子類,僅增加了兩個operation方法,為了能夠使用std::lower_bound這個模板函式
而在ip_geo_using_a.tar.gz這個例子中,通過編譯巨集控制struct ip_geo_info在c和c++中有不同形態
使用這兩個技巧的前提是,ippair和ip_geo_info這兩個結構/形態必須擁有相同的資料部分,至少說一方包含另外一方,實際測試這兩個結構的大小都是12個位元組
**示例鏈結
c 與IDL混編問題
將原有的idl計算模組整合到新的環境中後在計算的時候出錯 attempted to read or write protected memory.this is often anindication that other memory is corrupt.跟蹤 發現getnameddata獲取狀態...
python與C混編的執行邏輯
之前遇到過乙個c語言呼叫python的問題,是載入python版本可以在初始化前設定,如果不設定,會使用預設路徑 usr bin python.設定方法為在py initialize呼叫前使用py setprogramname,即可呼叫指定版本的python 當然還有乙個問題,就是寫了乙個pytho...
Makefile C與C 混編的簡單寫法
目錄結構 socket中是基本的socket類,except是捕捉異常類,include 是標頭檔案,basetype.h等,主程式檔案在當前目錄 target 目標檔案 obj dir this 中間檔案存放目錄 compile.cpp和compile.c 編譯 source paths 原始碼....