C與C 的混編方法

2021-06-26 19:29:44 字數 3594 閱讀 9632

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 原始碼....