• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

      基于C++/CLI實(shí)現(xiàn)托管代碼與非托管代碼的交互

      2013-10-20 08:36:00馮士德
      微型電腦應(yīng)用 2013年1期
      關(guān)鍵詞:調(diào)用實(shí)例代碼

      馮士德

      0 引言

      由于托管代碼與非托管代碼在運(yùn)行機(jī)制上存在差異,導(dǎo)致了這兩者間無法實(shí)現(xiàn)直接的交互。雖然微軟在.Net Framework中提供了P/Invoke技術(shù)來解決托管代碼與非托管代碼之間的互操作問題[1]。但是使用 P/Invoke的 DllImport方法,僅能實(shí)現(xiàn)在托管代碼中調(diào)用非托管代碼中的函數(shù),而無法實(shí)現(xiàn)對非托管代碼中類的引用。為了解決這個(gè)問題,通常做法是建立函數(shù)接口對非托管代碼中的類進(jìn)行包裝,然后在托管代碼中使用 P/Invoke方法,通過調(diào)用函數(shù)接口間接調(diào)用非托管代碼中所定義的類。但是在托管代碼與非托管代碼互操作頻繁的項(xiàng)目中,通過函數(shù)接口調(diào)用非托管代碼中的類,將會破壞面向?qū)ο蟮木幊趟枷?,同時(shí)影響代碼的執(zhí)行效率。為了解決這一問題,本文就使用 C++/CLI語言實(shí)現(xiàn)在托管代碼與非托管代碼之間的交互進(jìn)行了研究,并以 C#語言為例解釋說明了其具體的實(shí)現(xiàn)的方法。

      1 C++/CLI與托管/非托管代碼

      C++/CLI是標(biāo)準(zhǔn) C++語言與CLI(Common Language Infrastructure)的集成。在代碼編制方法上,它在保留了標(biāo)準(zhǔn) C++語言的語法并對其進(jìn)行了擴(kuò)展以符合 CLI語言的要求。所以可以將C++/CLI語言簡單的看作為標(biāo)準(zhǔn)C++語言的一個(gè)擴(kuò)展。但在代碼編譯與執(zhí)行的原理上,它卻與標(biāo)準(zhǔn)C++語言截然不同,它遵守了CLI語言的規(guī)范。與其他CLI語言相同,C++/CLI語言在被編譯時(shí)將會被編譯成托管的微軟中間語言(MSIL)代碼,之后再由實(shí)時(shí)(JIT)編譯器在執(zhí)行時(shí)將中間語言代碼編譯為本機(jī)代碼后執(zhí)行[2]。不過又區(qū)別于其他CLI語言,C++/CLI代碼中以#pragma unmanaged標(biāo)記顯式標(biāo)注的代碼段將被直接編譯為本地二進(jìn)制代碼。所以C++/CLI代碼在經(jīng)過編譯,最后所生成的是托管代碼與非托管代碼的混合程序集,如圖1所示:

      圖1 C++/CLI代碼編譯機(jī)制

      可見C++/CLI代碼身處托管代碼與非托管代碼之間,其3者關(guān)系,如圖2所示:

      圖2 C++/CLI、托管代碼、非托管代碼關(guān)系

      C++/CLI代碼,就好似在托管世界與非托管世界之間架起了一座橋梁,打通了兩者之間的壁壘。通過在源代碼層次的交互,C++/CLI提供了一個(gè)非常有價(jià)值的跨編程語言的集成方式。借助于這種方式,可以將非托管代碼中的本地類在托管的世界中發(fā)布,這使得在同一個(gè)軟件項(xiàng)目中,充分調(diào)動(dòng)托管代碼世界與非托管代碼世界中,豐富軟件資源成為了可能。

      2 交互方法

      由于托管代碼與非托管代碼的實(shí)現(xiàn)機(jī)制不同,所以在這兩者間無法實(shí)現(xiàn)直接的函數(shù)調(diào)用或數(shù)據(jù)傳遞操作。而C++/CLI代碼恰恰介于托管與非托管之間,所以以C++/CLI代碼為中介,實(shí)現(xiàn)托管與非托管代碼之間的交互,是一個(gè)可行的方法,也是本文所研究的重點(diǎn)。

      2.1 基本思想

      以C++/CLI代碼為中介,實(shí)現(xiàn)托管代碼與非托管代碼交互的方式,如圖3所示:

      圖3 托管代碼與非托管代碼交互方式

      作為托管代碼與非托管代碼之間的中介,C++/CLI代碼必須完成以下兩項(xiàng)主要工作:

      a) 在托管代碼與非托管代碼之間傳遞數(shù)據(jù)

      b) 在托管代碼與非托管代碼之間轉(zhuǎn)換內(nèi)存地址

      C++/CLI代碼通過對非托管代碼中的類,進(jìn)行包裝來完成以上兩項(xiàng)工作。

      首先,使用C++/CLI代碼聲明一個(gè)非托管類的包裝類。此包裝類中必須含有一個(gè)指向非托管類實(shí)例的指針,這樣,包裝類便能夠通過這個(gè)指針,將托管代碼對非托管類實(shí)例的操作請求,傳遞給非托管類實(shí)例。

      然后,為包裝類添加構(gòu)造函數(shù)與析構(gòu)函數(shù)。在構(gòu)造函數(shù)中實(shí)現(xiàn)生成非托管類實(shí)例的操作,并將其地址賦給包裝類中非托管類實(shí)例的指針。在析構(gòu)函數(shù)中則應(yīng)實(shí)現(xiàn)刪除非托管類實(shí)例的操作。

      最后,為包裝類添加與非托管類中的公共成員屬性及公共成員函數(shù)對應(yīng)的成員屬性與成員函數(shù)。當(dāng)托管代碼需要讀寫非托管類中的公共成員屬性時(shí),托管代碼通過讀寫包裝類中相應(yīng)的成員屬性間接實(shí)現(xiàn)讀寫操作。托管代碼對非托管類中成員函數(shù)的調(diào)用操作亦是如此。

      可見使用C++/CLI代碼進(jìn)行集成是一種代碼級別的集成方式,通過 C++/CLI代碼可以非常方便地對非托管代碼中的類進(jìn)行包裝。所生成的包裝類完全符合CLI代碼規(guī)范,并可以在托管代碼中自由地調(diào)用,因此能夠?qū)崿F(xiàn)托管代碼與非托管代碼之間的無縫集成。

      2.2 交互方法舉例

      本節(jié)以C#語言為例,說明使用C++/CLI語言對非托管代碼中的導(dǎo)出類進(jìn)行包裝的具體方法。并以非托管代碼中的導(dǎo)出類UnmanagedClass為樣例對其進(jìn)行包裝,其頭文件聲明如下:

      UnmanagedClsss類中包括一個(gè) int型的公共屬性iParamA、一個(gè)公共函數(shù)Add以及相應(yīng)的構(gòu)造函數(shù)和析構(gòu)函數(shù)。Add函數(shù)實(shí)現(xiàn)了將兩個(gè)輸入?yún)?shù)相加并返回結(jié)果的簡單功能。這些函數(shù)與屬性均為公共類型(pubulic)。由于非托管類中私有類型(private)的成員屬性與成員函數(shù)僅在類的內(nèi)部可見無需導(dǎo)出,所以在該例中省略了私有成員屬性與私有成員函數(shù)。

      為了將UnmanagedClass包裝為托管代碼中的類,使用C++/CLI代碼聲明 ManagedClass類對其進(jìn)行包裝。ManagedClass的頭文件聲明如下:

      ManagedClass作為 UnmanagedClass被封裝后的托管類,根據(jù)托管代碼的規(guī)則,在聲明ManagedClass時(shí)必須同時(shí)指定其namespace。在本例中將其設(shè)為“SampleSolution”。

      在 ManagedClass中聲明一個(gè) protected的成員屬性pInstance,并設(shè)置該成員屬性為UnmanagedClass類的指針。當(dāng)ManagedClass的構(gòu)造函數(shù)被調(diào)用時(shí),在構(gòu)造函數(shù)中生成被包裝類UnmanagedClass的實(shí)例,并將其地址保存于這個(gè)指針屬性中。之后所有對ManagedClass的操作都將通過此指針傳遞給UnmanagedClass。ManagedClass的構(gòu)造與析構(gòu)函數(shù)如下:

      為了將UnmanagedClass中的每個(gè)公共成員屬性導(dǎo)出,在ManagedClass中為UnmanagedClass的每個(gè)公共成員屬性建立一個(gè)對應(yīng)的屬性。對ManagedClass中的公共屬性執(zhí)行讀寫操作時(shí),將實(shí)際的操作通過ManagedClass::pInstance指針傳遞給 UnmanagedClass實(shí)例,代碼舉例如下:

      從示例代碼中可知,當(dāng)對ManagedClass的iParamA執(zhí)行讀操作時(shí),實(shí)際返回的是由ManagedClass::pInstance所指UnmanagedClass實(shí)例中成員屬性iParamA的值。對iParamA的寫操作也類似,實(shí)際寫入的是UnmanagedClass實(shí)例中成員屬性iParamA。

      為了將ManagedClass中的每個(gè)公共成員函數(shù)導(dǎo)出,也采取與導(dǎo)出公共成員屬性相似的方法。在ManagedClass中為UnmanagedClass的每個(gè)公共成員函數(shù)聲明一個(gè)對應(yīng)的公共成員函數(shù),代碼舉例如下:

      當(dāng)ManagedClass中的成員函數(shù)被調(diào)用時(shí),此調(diào)用操作將通過 ManagedClass::pInstance指針找到 UnmanagedClass中所對應(yīng)的成員函數(shù),并將調(diào)用參數(shù)傳遞給它,然后執(zhí)行該函數(shù)并將返回值返回給ManagedClass的成員函數(shù),最后由ManagedClass的成員函數(shù)將返回值返回給函數(shù)調(diào)用者。

      3 執(zhí)行效率測試及其結(jié)果分析

      為了進(jìn)一步研究使用C++/CLI語言技術(shù)實(shí)現(xiàn)托管代碼與非托管代碼之間交互的方式是否會降低非托管代碼執(zhí)行效率的問題,本文以冒泡排序法為案例對該交互方式的代碼執(zhí)行效率進(jìn)行了測試。

      3.1 測試方法

      首先以 C++語言編制一個(gè)基于非托管代碼的 DLL文件,該DLL文件中包應(yīng)含一個(gè)實(shí)現(xiàn)冒泡排序法的導(dǎo)出類。然后使用C++/CLI語言對算法DLL文件進(jìn)行包裝,生成一個(gè)介于托管與非托管之間的DLL文件。最后使用C#語言編寫一個(gè)調(diào)用程序來調(diào)用這個(gè)DLL文件,以此實(shí)現(xiàn)冒泡排序的功能。

      同時(shí)作為對比試驗(yàn)的參照物,使用 C++語言編寫另一個(gè)調(diào)用程序。該程序直接調(diào)用非托管的算法DLL文件實(shí)現(xiàn)冒泡排序功能。

      通過對比這兩個(gè)分別由C#語言與C++語言實(shí)現(xiàn)的調(diào)用程序的執(zhí)行時(shí)間,便可以判斷經(jīng)過包裝后的非托管代碼的執(zhí)行效率是否會降低。所生成的實(shí)驗(yàn)用DLL文件與調(diào)用程序的結(jié)構(gòu),如圖4所示:

      圖4 試驗(yàn)用程序結(jié)構(gòu)

      3.2 試驗(yàn)結(jié)果

      為了得到相對準(zhǔn)確的試驗(yàn)結(jié)果,使用 C#調(diào)用程序與C++調(diào)用程序分別執(zhí)行對2萬、4萬、6萬、8萬、10萬個(gè)隨機(jī)數(shù)的排序操作,并分別記錄其執(zhí)行時(shí)間。

      同時(shí)考慮到Windows是多線程操作系統(tǒng),為了減少線程間調(diào)度對本次試驗(yàn)結(jié)果產(chǎn)生的影響,在執(zhí)行測試程序前已關(guān)閉了所有其它應(yīng)用程序。并且對各個(gè)數(shù)量級別的測試分別執(zhí)行 10次并取其平均數(shù)作為最后的試驗(yàn)結(jié)果。在CPU 為2.4GHz、內(nèi)存2G、Win7操作系統(tǒng)的普通臺式機(jī)環(huán)境中,實(shí)際測試結(jié)果,如圖5所示:

      圖5 試驗(yàn)結(jié)果對比

      由圖5中顯示的試驗(yàn)數(shù)據(jù)可知,經(jīng)過包裝的非托管代碼在托管代碼中的執(zhí)行效率與直接在非托管代碼中的執(zhí)行效率的差距在上下千分之三之內(nèi),在部分情況下甚至要稍高于直接在非托管代碼中的執(zhí)行效率。通過對比這兩組試驗(yàn)數(shù)據(jù),可以近似認(rèn)為非托管代碼在經(jīng)過包裝后的執(zhí)行效率等同于包裝前的執(zhí)行效率,代碼執(zhí)行效率幾乎不受包裝影響。

      4 結(jié)束語

      當(dāng)前微軟.Net平臺的發(fā)展勢頭正勁,托管代碼的執(zhí)行效率也正逐步逼近非托管代碼,很多軟件開發(fā)公司也都將.Net作為其主要產(chǎn)品開發(fā)平臺。.Net平臺的發(fā)展正按照微軟的規(guī)劃突飛猛進(jìn),好似無所不能。但是C++語言經(jīng)過了這么多年的發(fā)展與積累,數(shù)以萬計(jì)的程序員以C++語言開發(fā)了海量的應(yīng)用。特別是以科學(xué)計(jì)算、底層硬件通信為代表的,對代碼執(zhí)行效率、系統(tǒng)響應(yīng)速度有較高要求的應(yīng)用,多以C++語言實(shí)現(xiàn)。如果僅以.Net為開發(fā)平臺,將不得不放棄在以 C++語言為代表的非托管代碼世界中現(xiàn)存的眾多寶貴軟件資源。而隨著 C++/CLI語言的出現(xiàn),它以一種極其簡單且高效的方式,打通了托管世界與非托管世界之間的壁壘,為我們在.Net平臺的開發(fā)中充分的利用現(xiàn)有非托管軟件資源提供了有效的途徑。

      當(dāng)前能夠?qū)崿F(xiàn)在托管代碼與非托管代碼之間交互的技術(shù)有很多,例如利用隨機(jī)數(shù)據(jù)文件作為交互中介[3]等。但是每種交互方式都相對的存在其優(yōu)缺點(diǎn),在軟件項(xiàng)目中必須根據(jù)具體需求來決定選取何種交互方法。所以針對各種實(shí)現(xiàn)托管代碼與非托管代碼交互技術(shù)之間優(yōu)缺點(diǎn)的研究還值得繼續(xù)深入。

      [1]彭邦倫.C#托管代碼調(diào)用非托管代碼參數(shù)傳遞的實(shí)現(xiàn)方式.[J]軟件導(dǎo)刊2011,10(1)

      [2]鄭阿奇.Visual C++ .NET 2010 開發(fā)實(shí)踐-基于C++/CLI.[M]北京,電子工業(yè)出版社 2010年 12月 ISBN:978-7-121-12153-1

      [3]何淼,崔松健.一種基于隨機(jī)文件的C#與非托管C代碼交互模式.[J]信息化研究2011,37(2)

      [4]Jeffrey Richter.CLR via C#(第3版).[M]清華大學(xué)出版社 2010年9月 ISBN:978-7-302-23259-9

      [5]錢能.C++程序設(shè)計(jì)教程.[M]清華大學(xué)出版社, 1999年4月 ISBN:7-302-03421-4

      [6]蔡昭權(quán).C#和C++數(shù)據(jù)傳遞的研究與實(shí)現(xiàn).[J]計(jì)算機(jī)應(yīng)用與軟件2009,26(3)

      猜你喜歡
      調(diào)用實(shí)例代碼
      核電項(xiàng)目物項(xiàng)調(diào)用管理的應(yīng)用研究
      LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
      創(chuàng)世代碼
      創(chuàng)世代碼
      創(chuàng)世代碼
      創(chuàng)世代碼
      基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
      完形填空Ⅱ
      完形填空Ⅰ
      利用RFC技術(shù)實(shí)現(xiàn)SAP系統(tǒng)接口通信
      通化市| 咸阳市| 郑州市| 光泽县| 梁平县| 陈巴尔虎旗| 子长县| 金平| 门源| 怀安县| 桂东县| 昌图县| 永丰县| 奉节县| 龙南县| 固安县| 依安县| 延安市| 瑞丽市| 北川| 垫江县| 苏尼特右旗| 察隅县| 定陶县| 西平县| 汕头市| 沙坪坝区| 淳安县| 英吉沙县| 平度市| 收藏| 永顺县| 航空| 额尔古纳市| 抚州市| 永寿县| 霸州市| 舞阳县| 扎鲁特旗| 邵阳市| 孟连|