胡亞鵬朱東華郭小賓李玉芝李 影馮光輝
(1.河南油田測(cè)井公司 河南南陽) (2.河南油田通信公司 河南南陽)
VC++和FORTRAN混合編程在陣列感應(yīng)數(shù)值模擬軟件中的應(yīng)用
胡亞鵬1朱東華1郭小賓1李玉芝2李 影1馮光輝1
(1.河南油田測(cè)井公司 河南南陽) (2.河南油田通信公司 河南南陽)
為了利用已有成熟的FORTRAN程序,避免重復(fù)編程和資源浪費(fèi),節(jié)省編程時(shí)間,在工程與科學(xué)研究中C/C++和Fortran混合編程有很大的應(yīng)用價(jià)值。主要論述了VisualC++和Fortran混合編程中動(dòng)態(tài)鏈接庫方法。闡明了如何通過CompaqVisualFortran6.x生成動(dòng)態(tài)鏈接庫,VisualC++中如何調(diào)用生成動(dòng)態(tài)鏈接庫的方法。并通過兩者的混合編程實(shí)現(xiàn)陣列感應(yīng)測(cè)井?dāng)?shù)值模擬軟件的開發(fā)。
混合編程;動(dòng)態(tài)鏈接庫;陣列感應(yīng)響應(yīng)
隨著石油測(cè)井行業(yè)的發(fā)展,由于陣列感應(yīng)測(cè)井[1]在劃分薄層、描述地層電阻率徑向變化、識(shí)別油水層等方面體現(xiàn)出的優(yōu)越性,在石油測(cè)井行業(yè)中的地位越來越重要。而陣列感應(yīng)響應(yīng)計(jì)算技術(shù)在陣列感應(yīng)測(cè)井研究中起著非常重要的作用,因此有必要開發(fā)陣列感應(yīng)數(shù)值模擬軟件。
實(shí)現(xiàn)數(shù)值計(jì)算的主流平臺(tái)是CompaqVisualFortran6.x,但它卻不適合作為應(yīng)用系統(tǒng)的集成開發(fā)平臺(tái),大部分Fortran程序是一個(gè)沒有圖形界面的命令行程序,獨(dú)立運(yùn)行時(shí)會(huì)出現(xiàn)一個(gè)命令行窗口,直到程序運(yùn)行結(jié)束,參數(shù)的輸入及計(jì)算結(jié)果查看非常不方便。為了克服以上缺點(diǎn),Fortran程序可以“組件”(主流組件為DLL)形式融入到其它語言工具開發(fā)的應(yīng)用系統(tǒng)中。在32位Windows操作系統(tǒng)中,VisualC++為應(yīng)用系統(tǒng)的集成主流開發(fā)平臺(tái)[2]。因此,本文重點(diǎn)探討在VisualFortran6.x中編譯生成 Win32DLL,以及在Visual C++對(duì)生成DLL文件中過程實(shí)施調(diào)用的混合編程實(shí)現(xiàn)陣列感應(yīng)測(cè)井?dāng)?shù)值模擬軟件的開發(fā)。
陣列感應(yīng)響應(yīng)計(jì)算技術(shù)在陣列感應(yīng)測(cè)井研究中起著非常重要的作用,它是儀器設(shè)計(jì),信號(hào)合成處理,反演和測(cè)井響應(yīng)異常解釋的基礎(chǔ)。目前為止,陣列感應(yīng)響應(yīng)計(jì)算已發(fā)展了很多方法,主要可分為解析解法、數(shù)值模式匹配法和有限元法三種方法。三種方法的特點(diǎn)是,解析解法可以計(jì)算一維縱向、徑向軸對(duì)稱旋轉(zhuǎn)地層,計(jì)算速度快;數(shù)值模式匹配法可以計(jì)算二維縱向、徑向軸對(duì)稱旋轉(zhuǎn)地層,計(jì)算速度較快;有限元法可以計(jì)算一般復(fù)雜地層,如傾斜地層等,其計(jì)算速度與網(wǎng)格剖分疏密有關(guān)。本文中計(jì)算陣列感應(yīng)響應(yīng)Fortran程序主要按數(shù)值模式匹配法編寫的。
混合語言編程涉及一種語言對(duì)用另一種語言編寫的函數(shù)、過程或者子過程的調(diào)用。本文中C/C++和Fortran混合編程主要是C/C++程序調(diào)用Fortran的過程或函數(shù)。為保證混合編程程序的正確運(yùn)行主要解決以下幾方面問題:
(1)調(diào)用約定一致性;
(2)函數(shù)命名的一致性;
(3)參數(shù)的正確傳遞,標(biāo)量參數(shù)和矢量參數(shù);
(4)VC++調(diào)用Fortran生成的動(dòng)態(tài)鏈接庫(DLL)。
調(diào)用約定決定程序?qū)瘮?shù)如何調(diào)用,如何傳遞參數(shù),如何命名目標(biāo)函數(shù)名。在一種語言的編譯環(huán)境中,由編譯系統(tǒng)統(tǒng)一協(xié)調(diào)函數(shù)的調(diào)用方式,因此不存在調(diào)用約定不一致的問題[3]。但在混合編程中,由于在C/C++和Fortran混合編程中,不同的語言和編譯環(huán)境,加之各自的默認(rèn)調(diào)用約定又不完全一致,這就有可能導(dǎo)致程序鏈接錯(cuò)誤或執(zhí)行錯(cuò)誤。所以,調(diào)用約定的匹配是混合編程所要解決的關(guān)鍵問題。
CompaqVisualFortran6.x使用的三種調(diào)用約定(缺省約定(Default)、C約定和STDCALL約定)的參數(shù)傳遞方式、堆棧管理、可選參數(shù)等影響,見表1。
表1 CompaqVisualFortran6.x調(diào)用約定
表1中,name為程序中所定義的函數(shù)名,n為參數(shù)類型所占字節(jié)數(shù),十進(jìn)制表示。
函數(shù)是通過關(guān)鍵字DLLEXPORT實(shí)現(xiàn),三種調(diào)用約定根據(jù)實(shí)際需求選擇其中一種。
由于C/C++語言字母區(qū)分大小寫,Fortran不區(qū)分標(biāo)示符大小寫,C++編譯后目標(biāo)標(biāo)識(shí)符添加特定的修飾,使目標(biāo)標(biāo)識(shí)符發(fā)生改變。為避免連接失敗,必須協(xié)調(diào)C/C++和Fortran的命名約定,使編譯后目標(biāo)標(biāo)識(shí)符保持一致。而不同的調(diào)用約定,其命名約定也不相同。函數(shù)編譯后的命名有三種情況:大寫、小寫和大小寫混合。
C/C++和Fortran混合編程中參數(shù)傳遞主要包括:數(shù)據(jù)類型對(duì)應(yīng)和參數(shù)傳遞方式。數(shù)據(jù)類型見表2。在Fortran和VisualC++過程之間參數(shù)的傳遞方式有值傳遞和引用傳遞兩種方式,前者將參數(shù)值壓入堆棧,后者將參數(shù)地址壓入堆棧。為避免鏈接錯(cuò)誤,在混合語言編程中必須保證參數(shù)傳遞方式的一致性。Fortran參數(shù)傳遞方式取決于調(diào)用約定,其默認(rèn)參數(shù)傳遞方式為引用,如采用C和STDCALL約定,標(biāo)量參數(shù)(單個(gè)參數(shù))采用值傳遞,數(shù)組采用引用傳遞。除采用調(diào)用約定約束外,還可以通過屬性VALUE和REFERENCE使參數(shù)分別以值和引用傳遞,并忽略調(diào)用約定約束。數(shù)組參數(shù)只能通過引用方式傳遞,且通過數(shù)組名傳遞數(shù)組首地址。在混合編程中,應(yīng)通過屬性VALUE和REFERENCE明確參數(shù)傳遞方式,本文不推薦通過調(diào)用約定約束參數(shù)的傳遞方式。
表2 Fortran與C/C++對(duì)應(yīng)數(shù)據(jù)類型[3]
在數(shù)值計(jì)算編程中,類型相同的數(shù)據(jù)常常利用數(shù)組。和其它語言相比,Fortran90/95中對(duì)數(shù)組的操作非常方便。但在Fortran與C/C++語言的混合編程中,數(shù)組參數(shù)比較特殊,在Fortran中,數(shù)組是按列優(yōu)先在內(nèi)存中連續(xù)排列的,而C/C++中,數(shù)組是按行優(yōu)先在內(nèi)存中連續(xù)排列的。對(duì)于一維數(shù)組,兩種語言沒有任何區(qū)別。對(duì)于大于二維的數(shù)組需要特別對(duì)待,在傳遞多維數(shù)組參數(shù)時(shí),若兩種語言的數(shù)組存儲(chǔ)方式不同,需要在調(diào)用前后對(duì)數(shù)組形狀進(jìn)行調(diào)整,即C/C++中數(shù)組行與列交換。以上述函數(shù)QPROG中第三個(gè)參數(shù)WK(2,4)為例討論大于二維的數(shù)組參數(shù)傳遞。由于兩種語言的數(shù)組排列方式不同,C/C++中需對(duì)數(shù)組WK行列交行 ,如floatWK[2、4]。列出 C/C++和 Fortran 中數(shù)組 WK行列交換后的對(duì)應(yīng)關(guān)系,見表3。
表3 C/C++和Fortran中數(shù)組WK行列交換后的對(duì)應(yīng)關(guān)系
不管數(shù)組是按列存放還是按行存放,數(shù)組在內(nèi)存中都占據(jù)一串連續(xù)的存儲(chǔ)單元。因此,雖然兩種語言的數(shù)組下標(biāo)規(guī)定不同,但在數(shù)組參數(shù)傳遞時(shí)可以通過數(shù)組名和取數(shù)組首元素的地址傳遞,其后續(xù)元素就一一被傳遞。
鏈接DLL到應(yīng)用程序中有兩種方式:顯式鏈接(ExplicitLink)和隱式鏈接(ImplicitLink)。由于顯式鏈接比隱式鏈接更具靈活性,并可及時(shí)釋放內(nèi)存的特點(diǎn),所以一般采用顯式鏈接方式。在該方式中,VC++通過函數(shù)調(diào)用顯式裝載和卸載DLL,并通過函數(shù)指針來調(diào)用DLL的導(dǎo)出函數(shù)。使用顯式鏈接的基本方式調(diào)用LoadLibrary或AfxLoadLibrary裝載DLL并得到模塊句柄;調(diào)用GetProcAddress獲得導(dǎo)出函數(shù)指針;在使用完畢時(shí),調(diào)用FreeLibrary或AfxFreeLibrary釋放DLL。
陣列感應(yīng)正演計(jì)算是用Fortran語言編寫的。對(duì)有關(guān)的界面與圖形系統(tǒng)的開發(fā)部分用VisualC++語言來編寫,對(duì)陣列感應(yīng)正演數(shù)值計(jì)算部分用Fortran語言來編寫,在VisualC++中對(duì)Fortran中的函數(shù)進(jìn)行調(diào)用實(shí)現(xiàn)陣列感應(yīng)正演數(shù)值模擬計(jì)算軟件。
在C/C++和Fortran混合編程中,有兩種具體的實(shí)現(xiàn)形式:(1)靜態(tài)庫連接方式:將Fortran程序用CompaqVisualFortran6.x編譯器進(jìn)行編譯,產(chǎn)生靜態(tài)目標(biāo)文件 (lib文件),在VisualC++調(diào)用函數(shù)生成可執(zhí)行文件;(2)動(dòng)態(tài)庫連接方式:將Fortran程序用CompaqVisualFortran6.x編譯器進(jìn)行編譯,生成動(dòng)態(tài)連接庫(DLL)文件。在需要調(diào)用Fortran代碼時(shí),由VisualC++對(duì)其動(dòng)態(tài)調(diào)用。
筆者采用第二種連接方式實(shí)現(xiàn)C/C++和Fortran混合編程,具體實(shí)現(xiàn)過程如下。
(1)生成動(dòng)態(tài)連接庫
對(duì)陣列感應(yīng)正演計(jì)算Fortran程序需作以下修改:
再用CompaqVisualFortran6.x進(jìn)行編譯,分別形成動(dòng)態(tài)連接庫(DLL)與靜態(tài)連接庫 (LIB)。
(2)VisualC++中定義Fortran函數(shù)接口
首先將第一步生成的態(tài)連接庫(DLL)與靜態(tài)連接庫 (LIB)文件拷貝到工程所在文件夾中,其次在C++代碼中對(duì)靜態(tài)庫作如下聲明:
#pragmacomment(lib,”dipping.lib”)
最后在C++中定義Fortran函數(shù)接口,聲明如下:
extern”C”{void_stdcalldipping(intisub,intnsamp,int&nlayer,float&topft,intieo,floatfreq,floatdelft,float&rho,float&bedft,float&realrho,float&rxrho,float&sigmabm);}
(3)VisualC++中調(diào)用Fortran函數(shù)完成計(jì)算
計(jì)算結(jié)果如圖1中給出三層電阻率分別為1.0Ω·m、15.0Ω·m和1.0Ω·m的地層模型的高分辨率陣列感應(yīng)(HDIL)儀器的響應(yīng)結(jié)果。
圖1 HDIL模擬結(jié)果
VisualC++可以快速進(jìn)行界面和繪圖顯示開發(fā),而Fortran在數(shù)值運(yùn)算中具有優(yōu)勢(shì)。利用兩者混合編程避免資源的浪費(fèi)和重復(fù)編程,提高了程序開發(fā)效率。在實(shí)際工程分析中取得良好的應(yīng)用效果。
[1] 張建華,劉振華,仵 杰.電法測(cè)井原理與應(yīng)用[M].西安:西北大學(xué)出版社,2002
[2] 周振紅,楊國錄,周洞汝,等.FORTRAN 與 VISUALBASIC混合編程的研究[J].武漢水利電力大學(xué)學(xué)報(bào),1999,42(2)
[3] 周振紅,李 強(qiáng).Fortran90/95高級(jí)程序設(shè)計(jì)[M].黃河水利出版社,1998
P631.8+1
B
1004-9134(2010)03-0079-03
2010-03-15 編輯:梁保江)
胡亞鵬,男,1981年生,助理工程師,2004年畢業(yè)于西安石油大學(xué)電子工程學(xué)院測(cè)控技術(shù)及儀器專業(yè),目前在河南南陽油田測(cè)井公司從事測(cè)井工作。郵編:473132