?1. 簡介
????????在python、java等語言中某些時(shí)候需要C做效率上的補(bǔ)充,在實(shí)際應(yīng)用中纬纪,需要做部分?jǐn)?shù)據(jù)的交互。因此就需要使用到鏈接庫(動(dòng)態(tài)庫和靜態(tài)庫滑肉,注:這里只介紹動(dòng)態(tài)庫)包各。而本文主要介紹的是跨平臺(tái)編譯:針對windows系統(tǒng)中的C++程序在linux編譯成動(dòng)態(tài)鏈接庫的過程。
2. .so及.dll介紹
2.1 .dll
? ? ? Windows下動(dòng)態(tài)鏈接庫以 .DLL?事實(shí)上和 EXE 文件一樣靶庙,同屬 PE 格式的執(zhí)行文件问畅。對于隱式的引用外部符號,需要把外部符號所在的位置寫在 PE 頭上。PE 加載器將從 PE 頭上找到依賴的符號表护姆,并加載依賴的其它 DLL 文件矾端。
? ? ?windows 可以存在一個(gè)dll 對另一個(gè) dll 的隱式依賴。windows的這種dll機(jī)制在著名教科書《程序員的自我修養(yǎng)》里仔細(xì)分析過卵皂。windows搞的這么麻煩秩铆,其實(shí)就是考慮到調(diào)用dll接口時(shí)的效率。
2.2 .so
? ? ?在Linix 下灯变,.so 為共享庫,是shared object,用于動(dòng)態(tài)連接的(通常還以 lib 開頭)殴玛。so 文件大多為 elf 執(zhí)行文件格式。當(dāng)它們需要的外部符號添祸,可以不寫明這些符號所在的位置滚粟。即通常so 文件并不知道它依賴的那些符號在哪些 so 里面。這些符號是由調(diào)用 dlopen 進(jìn)程運(yùn)行時(shí)提供的刃泌。dlopen 把這些符號通報(bào)給 dlopen 加載的 .so 文件凡壤,最終完成動(dòng)態(tài)鏈接。
? ? ?Linix?下一般不需要讓 so和 so 有隱式依賴關(guān)系蔬咬。效率方面linux也支持另一種so機(jī)制,編譯so時(shí)不加 -fPIC 的沐寺,可以用內(nèi)存空間換調(diào)用時(shí)間林艘。
2.3 .so和.dll比較分析
????由于操作系統(tǒng)的不同,他們在許多方面還是不盡相同混坞,下面從以下幾個(gè)方面進(jìn)行闡述狐援。
(1) 動(dòng)態(tài)庫程序編寫,在Windows系統(tǒng)下的執(zhí)行文件格式是PE格式究孕,動(dòng)態(tài)庫需要一個(gè)DllMain函數(shù)作為初始化的人口啥酱,通常在導(dǎo)出函數(shù)的聲明時(shí)需要有 _declspec(dllexport)關(guān)鍵字。Linux下的gcc編譯的執(zhí)行文件默認(rèn)是ELF格式厨诸,不需要初始化入口镶殷,亦不需要到函數(shù)做特別聲明,編寫比較方便微酬。
(2)動(dòng)態(tài)庫編譯绘趋,在windows系統(tǒng)下面,有方便的調(diào)試編譯環(huán)境颗管,通常不用自己去編寫makefile文件陷遮,但在linux下面,需要自己動(dòng)手去編寫makefile文件垦江。
(3)動(dòng)態(tài)庫調(diào)用方面帽馋,Windows和Linux對其下編制的動(dòng)態(tài)庫都可以采用顯式調(diào)用或隱式調(diào)用,但具體的調(diào)用方式也不盡相同。
(4) 動(dòng)態(tài)庫輸出函數(shù)查看绽族,在Windows中姨涡,有許多工具和軟件可以進(jìn)行查看DLL中所輸出的函數(shù),例如命令行方式的dumpbin以及VC++工具中的 DEPENDS程序项秉。在Linux系統(tǒng)中通常采用nm來查看輸出函數(shù)绣溜,也可以使用ldd查看程序隱式鏈接的共享對象文件。
(5)對操作系統(tǒng)的依賴娄蔼,這兩種動(dòng)態(tài)庫運(yùn)行依賴于各自的操作系統(tǒng)怖喻,不能跨平臺(tái)使用。因此岁诉,對于實(shí)現(xiàn)相同功能的動(dòng)態(tài)庫锚沸,必須為兩種不同的操作系統(tǒng)提供不同的動(dòng)態(tài)庫版本。
3. Linux下編譯.so
3.1? 附加庫?
? ? ?由于編譯的是Windows上的C++代碼涕癣,其中使用了附加的mysql哗蜈、opencv及ffmpeg庫,因此在Linux上重新編譯配置了相應(yīng)版本的庫坠韩。將相應(yīng)編譯好的庫下面lib和include路徑記錄下來在makefile中使用距潘。
3.2? Linux下C/C++及附加庫安裝配置
1)安裝C/C++編譯器:
http://blog.csdn.net/qq_21460229/article/details/78650900
2)C/C++程序編譯 與 調(diào)試
http://blog.csdn.net/haoel/article/details/2879
注:使用 ”-tui “ 選項(xiàng)可以將代碼顯示在文本用戶界面TUI≈桓椋可用光標(biāo)操控同時(shí)在下面的GDB shell中輸入命令: $?gdb -tui [可執(zhí)行程序名]
3)安裝eclipse進(jìn)行C/C++開發(fā)
http://blog.csdn.net/dugujiujian1124/article/details/46801823
4)安裝ffmpeg
https://my.oschina.net/u/1024107/blog/747807
5)安裝opencv3.3
http://blog.csdn.net/bh451326803/article/details/79047875
6)安裝mysql
http://blog.csdn.net/SmallTankPy/article/details/75451645
注:python導(dǎo)入mysql庫:$ sudo yum install MySQL-python
3.3? Makefile文件
? ? Makefile是類unix環(huán)境下(比如Linux)的類似于批處理的"腳本"文件音比。其基本語法是: 目標(biāo)+依賴+命令。?Makefile 文件描述了整個(gè)工程的編譯氢惋、連接等規(guī)則洞翩。有自己的書寫格式、關(guān)鍵字焰望、函數(shù)骚亿。像C 語言有自己的格式、關(guān)鍵字和函數(shù)一樣熊赖。
1) 規(guī)則:
Makefile文件由一系列規(guī)則(rules)構(gòu)成来屠。每條規(guī)則的形式如下,上面第一行冒號前面的部分,叫做"目標(biāo)"(target)震鹉,冒號后面的部分叫做"前置條件"(prerequisites)的妖;第二行必須由一個(gè)tab鍵起首,后面跟著"命令"(commands)足陨。
<target> : <prerequisites>
[tab] <commands>
2)語法:
包括:注釋嫂粟、回聲、通配符墨缘、模式匹配星虹、變量和賦值符零抬、變量和賦值符、自動(dòng)變量宽涌、判斷和循環(huán)平夜、函數(shù)等。
3)示例:
3.4? 注意的問題
????將windows下的C++代碼放在linux上編譯時(shí)除了一些頭文件導(dǎo)入路徑稍作修改外還有一些函數(shù)的修改如:
1)windows C++中的sprintf_s()? ->? Linux下的sprintf():
那么一舉兩得的方法是既能在Windows的C++中編譯也可以在linux上編譯的方法是:
在C++代碼中加入定義:
#ifdef _WIN64
#define _CRT_SECURE_NO_WARNINGS
#endif
2. windows C++中的_itoa_s()? ?-> Linux未定義:
我們可以使用sprintf()函數(shù)實(shí)現(xiàn)該功能:
char?buffer[20]??
int?n?=?123456;??
sprintf(buffer,"%d",n);
4. 應(yīng)用
4.1 python調(diào)用.so
? ? ?當(dāng)需要采用調(diào)用c++的程序的時(shí)候卸亮,需要對原有的數(shù)據(jù)加一個(gè)extern "C"封裝一下即可忽妒。采用g++編譯的代碼也需要的,原因可能是因?yàn)閏++編譯器編譯后的二進(jìn)制so文件中兼贸,對c++的函數(shù)進(jìn)行了重新的命名導(dǎo)致的段直。
4.2 ctypes庫?
????ctypes使得python能夠直接調(diào)用c語言開發(fā)的動(dòng)態(tài)鏈接庫,非常強(qiáng)大溶诞。
為了使用ctypes鸯檬,須依次完成以下步驟:
????* 編寫動(dòng)態(tài)連接庫程序
????* 載入動(dòng)態(tài)連接庫
????* 將Python的對象轉(zhuǎn)換為ctypes所能識(shí)別的參數(shù)
????* 使用ctypes的參數(shù)調(diào)用動(dòng)態(tài)連接庫中的函數(shù)
1)導(dǎo)入.so
import ctypes
so=ctypes.CDLL('/root/VideoCompute/libKeyFrame.so')?
so.get_hashfamily()
2) 數(shù)據(jù)類型
????ctypes?提供了一些原始C語言兼容的數(shù)據(jù)類型。第一列是在ctypes庫中定義的變量類型螺垢,第二列是C定義的變量類型喧务,第三列是Python在不使用ctypes時(shí)定義的變量類型。
5. 總結(jié)
參考連接:
http://blog.csdn.net/yang_lang/article/details/5926486
https://blog.codingnow.com/2006/11/windows_unix_dynamic_library.html
https://www.cnblogs.com/darling131499/p/4609097.html