![linux下C++動(dòng)態(tài)鏈接C++庫(kù)示例詳解_第1頁(yè)](http://file4.renrendoc.com/view/c82b0c5c515ead8a9598fe985233c473/c82b0c5c515ead8a9598fe985233c4731.gif)
![linux下C++動(dòng)態(tài)鏈接C++庫(kù)示例詳解_第2頁(yè)](http://file4.renrendoc.com/view/c82b0c5c515ead8a9598fe985233c473/c82b0c5c515ead8a9598fe985233c4732.gif)
![linux下C++動(dòng)態(tài)鏈接C++庫(kù)示例詳解_第3頁(yè)](http://file4.renrendoc.com/view/c82b0c5c515ead8a9598fe985233c473/c82b0c5c515ead8a9598fe985233c4733.gif)
![linux下C++動(dòng)態(tài)鏈接C++庫(kù)示例詳解_第4頁(yè)](http://file4.renrendoc.com/view/c82b0c5c515ead8a9598fe985233c473/c82b0c5c515ead8a9598fe985233c4734.gif)
![linux下C++動(dòng)態(tài)鏈接C++庫(kù)示例詳解_第5頁(yè)](http://file4.renrendoc.com/view/c82b0c5c515ead8a9598fe985233c473/c82b0c5c515ead8a9598fe985233c4735.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
一、介紹事實(shí)上,情況偶爾有些復(fù)雜,需要一些解釋。這正是寫(xiě)這篇miniHOWTO的緣由。理解這篇文檔的前提是對(duì)C/C++語(yǔ)言中dlopenAPI有基本的了解。/howtos/C++-dlopen-mini-HOWTO/二、問(wèn)題所在有時(shí)你想在運(yùn)行時(shí)加載一個(gè)庫(kù)(并使用其中的函數(shù)),這在你為你的程序?qū)懸恍┎寮蚰K架構(gòu)的時(shí)候經(jīng)常發(fā)生。在C語(yǔ)言中,加載一個(gè)庫(kù)輕而易舉(調(diào)用dlopen、dlsym和dlclose就夠了),但對(duì)C++復(fù)雜。(譯者注:也有人把它翻譯為“名字毀壞”,我覺(jué)得還是不翻譯好),另一部分是因?yàn)閐lopenAPI是用C語(yǔ)言實(shí)現(xiàn)的,因而沒(méi)有提供一個(gè)合適的方式來(lái)裝載類。我推薦您了解一下它,即使您對(duì)它不感興趣。因?yàn)檫@有助于您理解問(wèn)題是如何產(chǎn)生的,如何才能解決它們。1.NameMangling在每個(gè)C++程序(或庫(kù)、目標(biāo)文件)中,所有非靜態(tài)(non-static)函數(shù)在二進(jìn)制文件中都是以“符號(hào)(symbol)”形式出現(xiàn)的。是唯一的字符串,從而把各個(gè)函數(shù)在程序、庫(kù)、目標(biāo)文件中區(qū)分開(kāi)來(lái)。1/152/15這可能是因?yàn)閮蓚€(gè)非靜態(tài)函數(shù)的名字一定各不相同的緣故。而C++允許重載(不同的函數(shù)有相同的名字但不同的參數(shù)),并且有很多C所沒(méi)有的特性──比如類、成員函數(shù)、異常說(shuō)明──幾乎不可能直接用函數(shù)名為了解決這個(gè)問(wèn)題,C++采用了所謂的namemangling。它把函數(shù)名和一些信息(如參數(shù)數(shù)量和大小)雜糅在一起,改造成奇形怪狀,只有編譯器才懂的符號(hào)名。foo其中一個(gè)問(wèn)題是,C++標(biāo)準(zhǔn)(目前是[ISO14882])并沒(méi)有定義名字必須如何被mangle,所以每個(gè)編譯器都按自己的方式來(lái)進(jìn)行namemangling。有些編譯器甚至在不同版本間更換mangling算法(尤其是g++2.x和3.x)。但可能僅僅限于您手頭的這個(gè)編譯器而已,而無(wú)法在下一版編譯器下工作。使用dlopenAPI的另一個(gè)問(wèn)題是,它只支持加載函數(shù)。ternCC++有個(gè)特定的關(guān)鍵字用來(lái)聲明采用Cbinding的函數(shù):externC。只有非成員函數(shù)才能被聲明為extern"C",并且不能被重載。C,可以使用任何C++特性和各種類型的參數(shù)。3/152.加載函數(shù)在C++中,函數(shù)用dlsym加載,就像C中一樣。不過(guò),該函數(shù)要用extern"C"限定符聲明代碼://----------//main.cpp://----------#include<iostream>#include<dlfcn.h>intmain(){usingstd::cout;usingstd::cerr;cout<<"C++dlopendemo\n\n";//openthelibrarycout<<"Openinghello.so...\n";void*handle=dlopen("./hello.so",RTLD_LAZY);if(!handle){cerr<<"Cannotopenlibrary:"<<dlerror()<<'\n';return1;}//loadthesymbolcout<<"Loadingsymbolhello...\n";typedefvoid(*hello_t)();//reseterrorsdlerror();4/15hello_thello=(hello_t)dlsym(handle,"hello");constchar*dlsym_error=dlerror();if(dlsym_error){cerr<<"Cannotloadsymbol'hello':"<<dlsym_error<<'\n';dlclose(handle);return1;}//useittodothecalculationcout<<"Callinghello...\n";ello//closethelibrarycout<<"Closinglibrary...\n";dlclose(handle);}//----------//hello.cpp://----------#include<iostream>extern"C"voidhello(){std::cout<<"hello"<<'\n';}externC號(hào)名。ernC上面示例中使用的那種內(nèi)聯(lián)(inline)形式extern"C",5/15第一種內(nèi)聯(lián)形式聲明包含兩層意義:外部鏈接(externlinkage)和C語(yǔ)言鏈接(languageinkage而第二種僅影響語(yǔ)言鏈接。代碼:extern"C"intfoo;extern"C"voidbar();和代碼:extern"C"{externintfoo;externvoidbar();}代碼:extern"C"intfoo;和代碼:extern"C"{tfoo}是不同的物事(譯者注:簡(jiǎn)言之,前者是個(gè)聲明;而后者不僅是聲明,也可以是定義)。進(jìn)一步的解釋請(qǐng)參考[ISO14882],7.5,特別注意第7段;或者參考[STR2000],9.2.4。在用extern的變量尋幽訪勝之前,請(qǐng)細(xì)讀“其他”一節(jié)中羅列的文檔。3.加載類加載類有點(diǎn)困難,因?yàn)槲覀冃枰惖囊粋€(gè)實(shí)例,而不僅僅是一個(gè)函數(shù)指針。我們無(wú)法通過(guò)new來(lái)創(chuàng)建類的實(shí)例,因?yàn)轭惒皇窃诳蓤?zhí)行文件中定義的,況且(有時(shí)候)6/15我們連它的名字都不知道。我們?cè)诳蓤?zhí)行文件中定義一個(gè)帶虛成員函數(shù)的接口基類,而在模塊中定義派生實(shí)現(xiàn)類。通常來(lái)說(shuō),接口類是抽象的(如果一個(gè)類含有虛函數(shù),那它就是抽象的)。這意味著必須提供一個(gè)清晰定義的接口──我們將定義一個(gè)接口類和派生實(shí)現(xiàn)類。中,我們會(huì)定義兩個(gè)附加的helper函數(shù),就是眾所周知的“類工廠函數(shù)(classfactoryfunctions)(譯者注:或稱對(duì)象工廠函數(shù))”。其中一個(gè)函數(shù)創(chuàng)建一個(gè)類實(shí)例,并返回其指針;另一個(gè)函數(shù)則用以銷毀該指針。這兩個(gè)函數(shù)都以extern"C"來(lái)限定修飾。然后我們就可以隨心所欲地創(chuàng)建和銷毀實(shí)例了。我們用一個(gè)一般性的多邊形類作為接口,而繼承它的三角形類(譯者注:正三角形類)作代碼://----------//main.cpp://----------#include"polygon.hpp"#include<iostream>#include<dlfcn.h>intmain(){usingstd::cout;usingstd::cerr;//loadthetrianglelibraryvoid*triangle=dlopen("./triangle.so",RTLD_LAZY);if(!triangle){cerr<<"Cannotloadlibrary:"<<dlerror()<<'\n';return1;}//reseterrorsdlerror();//loadthesymbolscreate_t*create_triangle=(create_t*)dlsym(triangle,"create");constchar*dlsym_error=dlerror();if(dlsym_error){cerr<<"Cannotloadsymbolcreate:"<<dlsym_error<<'\n';return1;}destroy_t*destroy_triangle=(destroy_t*)dlsym(triangle,"destroy");dlsym_error=dlerror();if(dlsym_error){cerr<<"Cannotloadsymboldestroy:"<<dlsym_error<<'\n';return1;}//createaninstanceoftheclasspolygon*poly=create_triangle();7/15//usetheclasspoly->set_side_length(7);cout<<"Theareais:"<<poly->area()<<'\n';//destroytheclassdestroy_triangle(poly);//unloadthetrianglelibrarydlclose(triangle);}主程序的編譯與運(yùn)行:$g++-Wall-g-rdynamic-ldlmain.cpp-ocompile_c++LIBc++$./compile_c++LIBc++Theareais:42.4352//----------//polygon.hpp://----------#ifndefPOLYGON_HPP#definePOLYGON_HPPclasspolygon{protected:doubleside_length_;ublicpolygon():side_length_(0){}8/159/15virtual~polygon(){}voidset_side_length(doubleside_length){side_length_=side_length;}virtualdoublearea()const=0;//thetypesoftheclassfactoriestypedefpolygon*create_t();typedefvoiddestroy_t(polygon*);#endif//----------//triangle.cpp://----------#include"polygon.hpp"#include<cmath>classtriangle:publicpolygon{ublicvirtualdoublearea()const{returnside_length_*side_length_*sqrt(3)/2;}/15//theclassfactoriesextern"C"polygon*create(){returnnewtriangle;}extern"C"voiddestroy(polygon*p){deletep;}動(dòng)態(tài)庫(kù)的編譯:$g++-Wall-g-fPIC-otriangle.so-sharedtriangle.cpp值得注意的地方:◆你必須(譯者注:在模塊或者說(shuō)共享庫(kù)中)同時(shí)提供一個(gè)創(chuàng)造函數(shù)和一個(gè)銷毀函數(shù),且不能在執(zhí)行文件內(nèi)部使用delete來(lái)銷毀實(shí)例,只能把實(shí)例指針傳遞給模塊的銷毀函數(shù)處這容易導(dǎo)致new-delete的不匹配調(diào)用,造成莫名其妙的內(nèi)存泄漏和段錯(cuò)誤。這在用不同的標(biāo)準(zhǔn)庫(kù)鏈接模塊和可執(zhí)行文件時(shí)也一樣。◆接口類的析構(gòu)函數(shù)在任何情況下都必須是虛函數(shù)(virtual)。因?yàn)榧词钩鲥e(cuò)的可能極小,近乎杞人憂天了,但仍舊不值得去冒險(xiǎn),反正額外的開(kāi)銷微不如果基類不需要析構(gòu)函數(shù),定義一個(gè)空的(但必須虛的)析構(gòu)函數(shù)吧,否則你遲早要遇到我向您保證。你可以在comp.lang.c++FAQ(/c++-faq-lite/)的于該問(wèn)題的信息。/*!*******************************************************************************\File*arith.h******************************************************************************#ifndef__ARITH_H__#define__ARITH_H__classArithmetic{protected:intm_iVarA;intm_iVarB;ublicvoidset_member_var(inta,intb){m_iVarA=a;m_iVarB=b;}ublicvirtualintadd()const=0;//intadd();intsub();intmul();intdiv);intmod();publicArithmetic():m_iVarA(0),m_iVarB(0){}virtual~Arithmetic(){}typedefArithmetic*create_t();typedefvoiddestroy_t(Arithmetic*);#endif/*!*******************************************************************************\File*arith.cpp******************************************************************************#include"arith.h"classarith:publicArithmetic{ublicvirtualintadd()const{return(m_iVarA+m_iVarB);}//theclassfactoriesextern"C"Arithmetic*create(inta,intb){returnnewarith;}extern"C"voiddestroy(Arithmetic*p){deletep;}編譯動(dòng)態(tài)庫(kù):$g++-Wall-g-fPIC-oarith.so-sharedarith.cpp主程序:/*!*******************************************************************************\File*main.cpp*\Brief/15*C++sourcecode*\Author*Hank******************************************************************************#include<iostream>#include<dlfcn.h>#include"arith.h"usingnamespacestd;intmain(intargc,char*argv[]){inta=4,b=3;intret=0;void*p_Handler=dlopen("./arith.so",RTLD_LAZY);if(!p_Handl
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年鄉(xiāng)村農(nóng)副產(chǎn)品采購(gòu)合同協(xié)議模板(2篇)
- 2025年交易會(huì)攤位制作協(xié)議樣本(2篇)
- 2025年個(gè)人挖掘機(jī)買賣合同(2篇)
- 2025年個(gè)人機(jī)械租賃合同協(xié)議(4篇)
- 2025年事業(yè)單位臨時(shí)工合同樣本(2篇)
- 寫(xiě)字樓裝修解除合同協(xié)議書(shū)
- 2025年度安全設(shè)施完善租賃住宅合同示例
- 旗艦店品牌形象裝修合同
- 寵物店裝修承攬協(xié)議
- 廠房裝修抵租合同模板
- 《信號(hào)工程施工》課件 項(xiàng)目一 信號(hào)圖紙識(shí)讀
- 基礎(chǔ)護(hù)理常規(guī)制度
- 針灸治療動(dòng)眼神經(jīng)麻痹
- 傾聽(tīng)幼兒馬賽克方法培訓(xùn)
- 設(shè)備日常維護(hù)及保養(yǎng)培訓(xùn)
- 鋼結(jié)構(gòu)實(shí)習(xí)報(bào)告
- 2024年建房四鄰協(xié)議范本
- FTTR-H 全光組網(wǎng)解決方案裝維理論考試復(fù)習(xí)試題
- 2024年安全生產(chǎn)月主題2024年學(xué)校安全生產(chǎn)月活動(dòng)方案
- 2024年廣東佛山市中醫(yī)院三水醫(yī)院招聘61人歷年高頻考題難、易錯(cuò)點(diǎn)模擬試題(共500題)附帶答案詳解
- 測(cè)繪保密協(xié)議書(shū)保密協(xié)議(2024版)
評(píng)論
0/150
提交評(píng)論