• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    Fortran與VB.NET的混合編程

    2017-07-24 14:13:25胡文清詹杰民
    關(guān)鍵詞:字符串數(shù)組調(diào)用

    胡文清,詹杰民

    (中山大學(xué)工學(xué)院應(yīng)用力學(xué)與工程系,廣東 廣州 510275)

    Fortran與VB.NET的混合編程

    胡文清,詹杰民

    (中山大學(xué)工學(xué)院應(yīng)用力學(xué)與工程系,廣東 廣州 510275)

    Fortran語言具有很高的執(zhí)行效率,廣泛地應(yīng)用于數(shù)值計算領(lǐng)域,積累了大量高效可靠的源程序,例如,Microsoft 公司的 IMSL Fortran程序庫,為科學(xué)計算提供了強大的工具。VB.NET是完全面向?qū)ο蟮恼Z言,與VB相比,VB.NET具有快速簡易地開發(fā)功能更強大的Windows程序的優(yōu)點。剖析了VB.NET通過動態(tài)鏈接庫模式調(diào)用Fortran的混合編程,針對變量、字符串、數(shù)組、結(jié)構(gòu)體、結(jié)構(gòu)體數(shù)組等情況給出對應(yīng)的調(diào)用方法,并給出了典型示例。為開發(fā)集合Fortran和VB.NET優(yōu)點,兼具高執(zhí)行效率和快速簡易開發(fā)能力的軟件提供技術(shù)支持。

    Fortran;VB.NET;混合編程

    Fortran編程語言于1954年由IBM工程師開發(fā),是世界上最早出現(xiàn)的計算機高級程序設(shè)計語言,廣泛應(yīng)用于科學(xué)和工程計算領(lǐng)域。Fortran語法簡明嚴(yán)謹(jǐn),接近數(shù)學(xué)公式的自然描述,可以直接對矩陣和復(fù)數(shù)進行運算,在計算機里具有很高的執(zhí)行效率。長久以來,F(xiàn)ortran積聚了一大批高效、可靠、經(jīng)過考驗的函數(shù)庫、軟件包等源程序。然而Fortran是面向過程的語言,在設(shè)計開發(fā)人機交互界面方面能力較弱,不利于圖形處理,因此一般采用混合編程的形式,使用其他易于開發(fā)軟件的編程語言開發(fā)軟件界面,利用Fortran編寫計算核心程序。

    在Windows XP和更早的時代,程序員經(jīng)常采用VB編程語言來進行軟件開發(fā)。Visual Basic是一種由 Microsoft 公司開發(fā)的結(jié)構(gòu)化的、模塊化的、面向?qū)ο蟮?、包含協(xié)助開發(fā)環(huán)境的事件驅(qū)動為機制的可視化程序設(shè)計語言。VB是世界上使用人數(shù)最多的開發(fā)語言之一。利用VB開發(fā)人機交互界面[1],計算核心程序用Fortran開發(fā)是普遍的選擇[2],VB和Fortran的混合編程方法也已被廣泛研究[3-4]。

    隨著科技的發(fā)展,現(xiàn)在的電腦平臺普遍從XP時代的32位x86更換至WIN7時代的64位x64,XP時代的開發(fā)平臺已不能滿足需求。在windows XP時代,Visual Basic的版本還是VB6.0,F(xiàn)ortran的標(biāo)準(zhǔn)還是77、90、95的CVF,關(guān)于這些版本的混合編程的研究已有很多;在64位時代,VB已升級為VB.NET。2005年,微軟宣布將不會再對非。NET版本的VB進行支持,因此將開發(fā)平臺升級至VB.NET已是大勢所趨。與VB相比,VB.NET是完全面向?qū)ο蟮恼Z言,功能更加強大,開發(fā)者可以更快速的可視化開發(fā)網(wǎng)絡(luò)應(yīng)用程序、網(wǎng)絡(luò)服務(wù)、Windows應(yīng)用程序和服務(wù)器端組件。但是,由于VB.NET是基于.NET框架的,所開發(fā)的程序都被編譯成微軟中間語言(Microsoft Intermediate Language)的中間代碼,然后通過.NET Framework的公共語言運行庫(Common Language Runtime)來執(zhí)行。在Visual Studio 2008以后的版本,Visual Basic.NET的特性已經(jīng)與原來的大有不同。由于改動太大,VB.NET對VB的向后兼容并不好。另一方面,F(xiàn)ortran也從CVF變化為2003、2008標(biāo)準(zhǔn)的Intel Fortran。因此VB和Fortran的混合編程方法并不能直接使用在VB.NET上,如何實現(xiàn)VB.NET和Fortran的混合編程,是本文的研究重點。另外,本文除了對變量、字符串、數(shù)組等一般情況的混合編程方法進行了研究外,還對結(jié)構(gòu)體、結(jié)構(gòu)體數(shù)組等情況進行了研究,基本包括了VB.NET和Fortran混合編程中可能遇到的所有情況。

    本文研究的開發(fā)平臺為64位WIN7,F(xiàn)ortran為Intel(R) Visual Fortran Compiler Professional 11.1.038 +Microsoft Visual Studio 2008,VB.NET為Microsoft Visual Studio 2010。

    1 混合編程的調(diào)用約定和實現(xiàn)方法

    VB.NET和Fortran的調(diào)用方法通常有2種[5]:第1種是VB.NET實用Shell命令直接調(diào)用Fortran編譯生成的exe文件,這種方法適合于計算量較大而交互操作不多的情況。但是這種方法VB.NET程序和Fortran程序是異步執(zhí)行的,并不利于數(shù)據(jù)的實時交互;第2種方法是將Fortran程序編譯成動態(tài)鏈接庫(Dynamic Link Library),在VB.NET里通過約定的接口動態(tài)調(diào)用。這種方法又細分為隱式鏈接和顯式鏈接,隱式鏈接需要將Fortran編譯生成的LIB文件加載到VB.NET的工程中,即可直接調(diào)用Fortran的DLL。顯式鏈接只需要Fortran編譯生成的DLL文件,但是需要在VB.NET程序中顯式聲明需要調(diào)用的Fortran過程和函數(shù)。由于隱式鏈接方法在更新Fortran的DLL時需要每次都加載新的LIB文件,并不方便,因此一般采用顯式鏈接方法來加載DLL。綜上,本文采用VB.NET顯式鏈接加載Fortran編譯生成的DLL的方法來實現(xiàn)Fortran與VB.NET的混合編程。

    不同的語言編寫的程序之間的過程調(diào)用存在較大差異,因此在混合編程時必須保證調(diào)用約定的匹配。Fortran一共有3種調(diào)用約定:C、STDCALL、Default,VB.NET的默認(rèn)調(diào)用約定為WinAPI,在32位Intel平臺上對應(yīng)于STDCALL。由于STDCALL調(diào)用約定用于調(diào)用Win32 API函數(shù),也是VB.NET的默認(rèn)調(diào)用約定,因此在Fortran處不采用默認(rèn)調(diào)用約定,而是使用STDCALL,以符合Win32 API規(guī)范,這需要在Fortran源程序中聲明[6-7]。

    表1 STDCALL調(diào)用約定的實現(xiàn)Table 1 Calling convention of STDCALL

    VB.NET通過.NET Framework的CLR來執(zhí)行,稱作托管代碼,而VB的代碼和Fortran編譯的DLL屬于非托管代碼。因此VB.NET與Fortran的混合編程方法相對于VB時期有了相當(dāng)?shù)淖兓@在本文后面部分再分別說明。

    1.1 Fortran部分實現(xiàn)方法

    Fortran編譯DLL時,可以采用function或者subroutine形式。由于subroutine可以利用虛參實現(xiàn)多個返回值,因此一般采用subroutine形式。以下是示例代碼段:

    subroutine ftest(na,nb,a,b)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES VALUE::na,nb

    !DEC$ ATTRIBUTES REFERENCE::a,b

    其中,!DEC$ ATTRIBUTES 語句用于定義該DLL工程的屬性。STDCALL定義了該子過程使用STDCALL調(diào)用約定,DLLEXPORT表明該子過程能被外部其他程序或DLL調(diào)用。ALIAS屬性定義了該子過程的別名,將編譯產(chǎn)生的目標(biāo)例程名限定為引號內(nèi)的名稱,以保持大、小寫混合。使用ALIAS屬性避免了在VB.NET的部分必須使用符合STDCALL調(diào)用約定的例程名稱,而是能按程序員個人的意愿決定該子過程的例程名。VALUE和REFERENCE定義了該子過程的參數(shù)是按值傳遞還是按地址傳遞。STDCALL調(diào)用約定的默認(rèn)參數(shù)傳遞約定是按值傳遞,而VALUE和REFERENCE屬性的定義會覆蓋調(diào)用約定對參數(shù)傳遞產(chǎn)生的影響,因此推薦將全部參數(shù)都顯式定義其參數(shù)傳遞方式。

    1.2 VB.NET部分實現(xiàn)方法

    在VB.NET里,聲明外部過程的語句如下:

    Declare [Ansi|Unicode|Auto] Sub|Function 〈名稱〉 Lib “〈庫〉” [Alias “〈別名〉”] [([argumentList])]

    對于1.1節(jié)定義的子過程,假設(shè)該DLL工程編譯的DLL為ftest.dll,該DLL文件放在工程運行目錄下,則VB.NET里使用Declare語句定義該過程,Call語句調(diào)用。以下是示例代碼段:

    Declare Ansi Sub FTest Lib "ftest.dll" (ByVal na As Integer, ByVal nb As Integer, ByRef a As Double, ByRef b As Long)

    Call FTest(na, nb, a, b)

    其中,Ansi用于指定VB.NET將所有的字符串封送為ANSI值。由于VB.NET的字符串使用Unicode編碼,而Fortran的字符串使用ANSI編碼,因此該處指定封送編碼。Sub語句指定該外部過程為過程。FTest為過程的名稱,與1.1節(jié)里ALIAS屬性定義的別名一致?!磶臁抵付ㄒ肈LL的路徑,這里使用的是相對路徑。Alias指定在VB.NET里的別名,并非必須。argumentList指定該過程的參數(shù)屬性,ByVal為按值傳遞,ByRef為按地址傳遞。VB.NET的參數(shù)屬性設(shè)置必須與Fortran的一致。

    2 變量傳遞

    VB.NET與Fortran的變量傳遞可以使用ByVal按值傳遞,也可以使用ByRef按地址傳遞。相比于VB,VB.NET對于Integer和Long的定義作了修改,因此程序員不能套用舊的VB定義。VB.NET與Fortran的常用數(shù)據(jù)類型對應(yīng)關(guān)系如表2所示[8-9]。

    表2 數(shù)據(jù)類型對應(yīng)關(guān)系Table 2 Data types correspondence

    以下是示例代碼段:

    Fortran

    subroutine ftest(na,nb,a,b)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES VALUE::na,nb

    !DEC$ ATTRIBUTES REFERENCE::a,b

    REAL(8)::a

    INTEGER(8)::b

    INTEGER(4):: na,nb

    VB.NET

    Declare Ansi Sub FTest Lib "ftest.dll" (ByVal na As Integer, ByVal nb As Integer, ByRef a As Double, ByRef b As Long)

    Dim a As Double

    Dim b As Long

    Dim na, nb As Integer

    Call FTest(na, nb, a, b)

    3 字符串傳遞

    Fortran的字符串傳遞時默認(rèn)會在參數(shù)的最后附加一隱藏參數(shù),該參數(shù)是字符串的長度,按值傳遞。通過設(shè)置調(diào)用約定和VALUE/REFERENCE屬性可以改變傳遞方式。表3為詳細情況[8]。

    VB.NET的字符串類型實際是以包含長度和地址信息的結(jié)構(gòu)體形式存儲的。因此,VB.NET和Fortran的字符串傳遞必須以以下形式實現(xiàn):

    表3 Fortran傳遞字符串的ATTRIBUTE屬性效果Table 3 Effect of ATTRIBUTE options on character strings passed as arguments in Fortran

    VB.NET使用按值傳遞,F(xiàn)ortran使用按地址傳遞。VB.NET使用按值傳遞將間接引用存儲字符串的結(jié)構(gòu)體,實際上傳遞的只有字符串的地址,與Fortran所期望的一致。

    在VB.NET里,字符串變量使用String定義,不能直接定義定長字符串,字符串長度在賦值后確定。同時,VB.NET字符串在最后會增加一個NULL字符作為結(jié)束標(biāo)志,因此VB.NET字符串的總長度為字符數(shù)加一?;旌暇幊虝r應(yīng)先對VB.NET的字符串賦初值,使其長度與Fortran定長字符串一致。

    Fortran里漢字的存儲是兩字節(jié)的ANSI碼,因此VB.NET里需要聲明Ansi屬性。Fortran里統(tǒng)計字符串長度時一個漢字占用2個長度,但是在VB.NET里,統(tǒng)計字符串長度時一個漢字只占1個長度。這點程序員編寫程序時應(yīng)注意。

    以下是示例代碼段:

    Fortran

    subroutine ftest(chtt,chtt2)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES REFERENCE::chtt,chtt2

    character*5::chtt,chtt2

    do i=1,len_trim(chtt)

    chtt2(i:i)=chtt(len_trim(chtt)-i+1:len_trim(chtt)-i+1)

    end do

    VB.NET

    Declare Ansi Sub FTest Lib "ftest.dll" (ByVal chtt As String, ByVal chtt2 As String)

    Dim chtt, chtt2 As String

    chtt = "a中cd"

    chtt2 = "aaaaa"

    Call FTest(chtt, chtt2)

    該代碼段的結(jié)果為chtt=”a中cd”,chtt2=”dc兄a”,觀察漢字的GBK碼(中D6D0,兄D0D6)可證上述結(jié)論。

    4 數(shù)組傳遞

    VB.NET和Fortran的數(shù)組傳遞只能使用按地址傳遞的方式。實際傳遞時VB.NET需要傳遞數(shù)組的第一個元素,按地址傳遞時這將傳遞給Fortran數(shù)組的開始地址,正如Fortran所需。

    以下是示例代碼段:

    Fortran

    subroutine ftest(c, ni, nj, nk, nl)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES VALUE::ni, nj, nk, nl

    !DEC$ ATTRIBUTES REFERENCE::c

    integer(4)::ni, nj, nk, nl

    real(4),dimension(1:ni,1:nj,1:nk,1:nl)::c

    VB.NET

    Declare Ansi Sub FTest Lib "ftest.dll" (ByRef c As Single, ByVal ni As Integer, ByVal nj As Integer, ByVal nk As Integer, ByVal nl As Integer)

    Dim ni, nj, nk, nl As Integer: Dim c(,,,) As Single

    ni = 5: nj = 4: nk = 3: nl = 2

    ReDim c(0 To nl-1, 0 To nk-1, 0 To nj-1, 0 To ni-1)

    Call FTest(c(0, 0, 0, 0), ni, nj, nk, nl)

    可以見到VB.NET構(gòu)造數(shù)組與Fortran有相當(dāng)大的不同。以下兩節(jié)將做出詳細描述。

    4.1 構(gòu)造VB.NET數(shù)組

    VB.NET的數(shù)組下標(biāo)必須是0,不同于VB,VB可以使用option base語句來修改下標(biāo)為0或1。盡管如此,VB.NET仍然可以構(gòu)建下標(biāo)不為0的數(shù)組。VB.NET采用CLR來執(zhí)行,而CLR數(shù)組可以使用Array.CreateInstance方法來指定數(shù)組創(chuàng)建的維數(shù)和每維的起始索引值。示例如下:

    Dim a(,,,), b(,,,) As Single

    ReDim a(0 To nl-1, 0 To nk-1, 0 To nj-1, 0 To ni-1)

    b = Array.CreateInstance(GetType(Single), {nl, nk, nj, ni}, {1, 1, 1, 1})

    a和b數(shù)組均為類型相同的四維數(shù)組,每維的大小相等,區(qū)別只是起始索引值不同,a從0開始,b從1開始。Array.CreateInstance方法的第1個屬性指定數(shù)組類型,第2個屬性指定每維的大小,第3個屬性指定每維的起始索引值。但是,這種方法不適用于一維數(shù)組。

    Dim c(), d() As Single: ReDim c(0 To ni-1)

    d = Array.CreateInstance(GetType(Single), {ni}, {1})

    這里c和d并不是類型相同的數(shù)組,c的類型為single[],而d的類型為single[*]。這是因為CLR中有一種數(shù)組是被特殊照顧的,那就是以0開始的一維數(shù)組,這種數(shù)組也被稱為“Vector”。Vector數(shù)組的類型為xxx[],Array.CreateInstance方法構(gòu)造的一維數(shù)組類型為xxx[*]。因此,當(dāng)使用一維數(shù)組混合編程時,VB.NET里只能以0開始,程序員需要注意和Fortran的不同;使用多維數(shù)組時,則可以使用Array.CreateInstance方法構(gòu)造和Fortran數(shù)組起始索引值一致的數(shù)組。

    4.2 VB.NET數(shù)組和Fortran數(shù)組的差異

    習(xí)慣上,我們將數(shù)組前面的維度稱為列,將后面的維度稱為行。Fortran 數(shù)組存儲時先改變前面的維度,因此,習(xí)慣稱之為“列優(yōu)先”存儲。而VB.NET數(shù)組與之相反,為“行優(yōu)先”存儲。舉例來說,VB.NET的數(shù)組 arr(4,3,2,1)與Fortran的arr(2,3,4,5)維度、大小均一致。

    以下是示例代碼段:

    Fortran

    subroutine ftest(c,d, ni, nj, nk, nl)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES VALUE::ni, nj, nk, nl

    !DEC$ ATTRIBUTES REFERENCE::c, d

    integer(4)::ni, nj, nk, nl

    real(4),dimension(1:ni,1:nj,1:nk,1:nl)::c,d

    do l=1,nl

    do k=1,nk

    do j=1,nj

    do i=1,ni

    d(i,j,k,l)=c(i,j,k,l)+i+nj*(j-1)+nj*nk*(k-1)+nj*nk*nl*(l-1)

    end do

    end do

    end do

    end do

    VB.NET

    Declare Ansi Sub FTest Lib "ftest.dll" (ByRef c As Single, ByRef d As Single, ByVal ni As Integer, ByVal nj As Integer, ByVal nk As Integer, ByVal nl As Integer)

    Dim ni, nj, nk, nl As Integer: Dim c(,,,), d(,,,) As Single

    ni = 5: nj = 4: nk = 3: nl = 2

    ReDim c(0 To nl-1, 0 To nk-1, 0 To nj-1, 0 To ni-1)

    ReDim d(0 To nl-1, 0 To nk-1, 0 To nj-1, 0 To ni-1)

    For l = 1 To nl

    For k = 1 To nk

    For j = 1 To nj

    For i = 1 To ni

    c(l-1,k-1, j-1,i-1)=i+nj*(j-1)+nj*nk*(k-1)+nj*nk*nl*(l-1)

    Next

    Next

    Next

    Next

    Call FTest(c(0, 0, 0, 0), d(0, 0, 0, 0), ni, nj, nk, nl)

    該代碼段的VB.NET部分對c按照“行優(yōu)先”賦值,F(xiàn)ortran部分對d按照“列優(yōu)先”賦值,并且加上c的對應(yīng)元素的值。結(jié)果d的每個元素的值均為c的對應(yīng)元素的值的兩倍, 證明了VB.NET數(shù)組與Fortran數(shù)組的差異。

    5 結(jié)構(gòu)體傳遞

    結(jié)構(gòu)體能夠?qū)崿F(xiàn)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在實際應(yīng)用中經(jīng)常使用到。因此VB.NET與Fortran混合編程的結(jié)構(gòu)體傳遞問題是研究的重點。在VB.NET里使用Structure語句定義結(jié)構(gòu)體,F(xiàn)ortran里使用type語句定義。VB.NET里結(jié)構(gòu)體的定義方法與VB相比有了很大的變化。VB.NET與Fortran使用結(jié)構(gòu)體傳遞需要注意以下2個問題:① VB.NET屬于托管代碼,定義的結(jié)構(gòu)體中的數(shù)組成員不能聲明初始大小,需要在結(jié)構(gòu)體里構(gòu)造初始化函數(shù)重定義數(shù)組大?。虎?無論是VB.NET還是Fortran,結(jié)構(gòu)體中的成員在存儲結(jié)構(gòu)上是自然對齊的,未必按照聲明次序來存儲。

    為解決這2個問題,需要在VB.NET里引入System.Runtime.InteropServices命名空間。利用此命名空間的MarshalAs屬性,可以指定如何在托管內(nèi)存與非托管內(nèi)存之間封送數(shù)據(jù),從而解決問題。

    以下是示例代碼段:

    Fortran

    subroutine ftest(tt)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES REFERENCE::tt

    type test

    sequence

    real(8)::cc

    integer(8)::iii

    real(4),dimension(0:3)::ccc

    character*12::str

    integer(4)::abc

    integer(4)::cba

    end type

    type(test)::tt

    VB.NET

    Imports System.Runtime.InteropServices

    Declare Ansi Sub FTest Lib "ftest.dll" (ByRef tt As test)

    Public Structure test

    Dim cc As Double: Dim iii As Long

    Dim ccc() As Single

    Dim str As String

    Dim abc As Integer: Dim cba As Integer

    Public Sub int()

    ReDim ccc(0 To 3)

    End Sub

    End Structure

    Dim tt As test: tt.int(): Call FTest(tt)

    如以上代碼段所示,為避免問題2,必須在VB.NET和Fortran都聲明為順序存儲。Fortran的實現(xiàn)方法是在結(jié)構(gòu)體定義里加入SEQUENCE屬性,VB.NET則是使用StructLayout屬性定義。LayoutKind.Sequential規(guī)定了結(jié)構(gòu)體成員按聲明順序存儲。CharSet屬性設(shè)置結(jié)構(gòu)體采用ANSI編碼,原因見第3部分。由于Fortran的默認(rèn)對齊長度為4字節(jié),因此VB.NET需要使用pack屬性設(shè)置結(jié)構(gòu)體存儲時按4字節(jié)對齊。

    由于VB.NET字符串不能聲明初始長度,結(jié)構(gòu)體里數(shù)組也不能聲明初始大小,因此需要采用MarshalAs屬性指明封送數(shù)據(jù)的大小。其中UnmanagedType.ByValArray作用于數(shù)組,UnmanagedType.ByValTStr作用于字符串,SizeConst屬性指定大小。為實際分配空間,需要在結(jié)構(gòu)體里構(gòu)造初始化函數(shù)int(),先初始化后再Call調(diào)用。

    利用MarshalAs屬性可以為結(jié)構(gòu)體的數(shù)組成員指明大小,但是這種方法只適用于一維數(shù)組。為了構(gòu)造VB.NET結(jié)構(gòu)體的多維數(shù)組成員,可行的方法是將多維數(shù)組拆分為多個一維數(shù)組,這樣就可以為每個維度數(shù)組設(shè)置MarshalAs屬性。

    以下是示例代碼段:

    Fortran

    subroutine ftest(tt)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES REFERENCE::tt

    type test

    sequence

    real(4),dimension(1:6,1:2)::ddd

    end type

    type(test)::tt

    VB.NET

    Imports System.Runtime.InteropServices

    Declare Ansi Sub FTest Lib "ftest.dll" (ByRef tt As test)

    Public Structure test

    Dim ddd() As structest

    Public Sub int()

    ReDim ddd(0 To 1)

    For i = 0 To 1

    ReDim ddd(i).ddda(0 To 5)

    Next

    End Sub

    End Structure

    Public Structure structest

    Dim ddda() As Single

    End Structure

    Dim tt As test: tt.int():Call FTest(tt)

    如以上代碼段所示,將二維數(shù)組拆分為2個一維數(shù)組,則可分別為每個維度設(shè)置MarshalAs屬性指明大小。需要注意的是,多維數(shù)組拆分時仍需注意第4部分所述的Fortran與VB.NET的存儲順序差異,保證Fortran遵照“列優(yōu)先”存儲,VB.NET遵照“行優(yōu)先”存儲。

    6 結(jié)構(gòu)體數(shù)組傳遞

    VB.NET與Fortran的結(jié)構(gòu)體數(shù)組傳遞不能使用第4部分?jǐn)?shù)組傳遞的方法,使用普通數(shù)組傳遞的方法時結(jié)構(gòu)體數(shù)組只能傳遞第一個數(shù)組元素。這是因為VB.NET屬于托管代碼,是CLR自動分配內(nèi)存地址和垃圾回收的。而Fortran屬于非托管代碼,VB.NET與Fortran進行結(jié)構(gòu)體數(shù)組傳遞時,托管對象可能已經(jīng)被垃圾回收器回收了,就會出問題。這里就需要使用System.Runtime.InteropServices命名空間的GCHandle類,該類提供用于從非托管內(nèi)存訪問托管對象的方法,利用其Alloc方法將托管對象設(shè)置為Pinned類型,固定對象的內(nèi)存地址,從而防止垃圾回收器移動對象回收掉。最后結(jié)束時使用Free方法釋放已分配的句柄。

    以下是示例代碼段:

    Fortran

    subroutine ftest(ta,na,nb)

    !DEC$ ATTRIBUTES STDCALL,DLLEXPORT::ftest

    !DEC$ ATTRIBUTES ALIAS:"FTest"::ftest

    !DEC$ ATTRIBUTES REFERENCE::tt

    type test

    sequence

    real(8)::cc

    integer(8)::iii

    real(4),dimension(0:3)::ccc

    character*12::str

    real(4),dimension(1:6,1:2)::ddd

    integer(4)::abc

    integer(4)::cba

    end type

    type(test),dimension(1:na,1:nb)::ta

    integer(4 ):: na,nb

    VB.NET

    Imports System.Runtime.InteropServices

    Declare Ansi Sub FTest Lib "ftest.dll" (ByVal pt As IntPtr, ByVal na As Integer, ByVal nb As Integer)

    Public Structure test

    Dim cc As Double: Dim iii As Long

    Dim ccc() As Single

    Dim str As String

    Dim ddd() As structest

    Dim abc As Integer: Dim cba As Integer

    Public Sub int()

    ReDim ccc(0 To 3): ReDim ddd(0 To 1)

    For i = 0 To 1

    ReDim ddd(i).ddda(0 To 5)

    Next

    End Sub

    End Structure

    Public Structure structest

    Dim ddda() As Single

    End Structure

    Dim na, nb As Integer: Dim ta(,) As test

    Dim ipt As IntPtr: Dim pt As IntPtr: ReDim ta(0 To nb-1, 0 To na-1)

    For l = 0 To nb -1

    For k = 0 To na-1

    ta(l, k).int()

    Next

    Next

    Dim tryon() As Byte: Dim gc As GCHandle

    ReDim tryon(Marshal.SizeOf(GetType(test))*na*nb-1)

    gc = GCHandle.Alloc(tryon, GCHandleType.Pinned): pt = gc.AddrOfPinnedObject

    For j = 0 To nb-1

    For i = 0 To na-1

    ipt = pt.ToInt32 + Marshal.SizeOf(GetType(test)) * i + Marshal.SizeOf(GetType(test)) * j * na

    Marshal.StructureToPtr(ta(j, i), ipt, True)

    Next

    Next

    Call FTest(pt, na, nb)

    For j = 0 To nb-1

    For i = 0 To na-1

    ipt = pt.ToInt32 + Marshal.SizeOf(GetType(test)) * i + Marshal.SizeOf(GetType(test)) * j * na

    ta(j, i) = Marshal.PtrToStructure(ipt, GetType(test))

    Next

    Next

    gc.Free()

    如以上代碼段所示,VB.NET和Fortran進行結(jié)構(gòu)體數(shù)組傳遞時需要注意以下3點:

    1) 使用GCHandle類來傳遞結(jié)構(gòu)體數(shù)組時,需要使用Byte數(shù)組來作數(shù)據(jù)存儲。這是因為來用于固定數(shù)組的GCHandle的Alloc方法不能以結(jié)構(gòu)體作為參數(shù),因此需要利用Byte數(shù)組作媒介。使用時需要將該Byte數(shù)組的大小重定義與結(jié)構(gòu)體數(shù)組的大小嚴(yán)格一致。單個結(jié)構(gòu)體的大小使用Marshal類的SizeOf語句獲得。

    2)使用IntPtr類型作為該Byte數(shù)組的指針來作為函數(shù)參數(shù)傳遞,這點與單一結(jié)構(gòu)體傳遞時直接將結(jié)構(gòu)體作為函數(shù)參數(shù)不同。IntPtr用于表示指針或句柄的平臺特定類型,使用GCHandle的AddrOfPinnedObject屬性將IntPtr變量指向該Byte數(shù)組的內(nèi)存首地址。利用Marshal的StructureToPtr方法通過IntPtr變量給Byte數(shù)組賦值,同樣調(diào)用后需要用Marshal的PtrToStructure方法通過IntPtr變量將Byte數(shù)組的值傳遞回目標(biāo)結(jié)構(gòu)體數(shù)組中。

    3)無論是給Byte數(shù)組賦值時還是將Byte數(shù)組的值傳遞回目標(biāo)結(jié)構(gòu)體數(shù)組,均需要使用循環(huán)結(jié)構(gòu)對目標(biāo)結(jié)構(gòu)體數(shù)組的每一個成員進行操作。這里仍然需要注意本文第4部分所述的Fortran與VB.NET的存儲順序差異,保證Fortran遵照“列優(yōu)先”存儲,VB.NET遵照“行優(yōu)先”存儲。

    7 總 結(jié)

    本文詳細介紹了Fortran與VB.NET在64位Windows平臺上混合編程的方法,并給出了相應(yīng)的示例。通過對變量、字符串、數(shù)組、結(jié)構(gòu)體、結(jié)構(gòu)體數(shù)組等情況的混合編程方法的研究,基本解決了在Fortran和VB.NET混合編程中可能出現(xiàn)的各種問題,從而為在64位平臺上,以DLL為紐帶充分發(fā)揮Fortran強大的計算能力和VB.NET的可視化程序開發(fā)提供了堅實的技術(shù)基礎(chǔ)。

    [1] 陳曉翔,柯棟,李芳,等. 非標(biāo)準(zhǔn)格式地理空間數(shù)據(jù)的GIS方式直接讀取研究[J]. 中山大學(xué)學(xué)報(自然科學(xué)版), 2002, 41(2): 117-118. CHEN X X, KE D, LI F, et al. A study of GIS-based direct reading of nonstandard geographic spatial data [J]. Acta Scientiarum Naturalium Universitatis Sunyatseni, 2002, 41(2): 117-118.

    [2] 劉祚秋,溫少榮,周翠英,等. 樁、土、剛性承臺相互作用下樁基內(nèi)力計算新方法[J]. 中山大學(xué)學(xué)報(自然科學(xué)版), 2004, 43(4): 33-37. LIU Z Q, WEN S R, ZHOU C Y, et al. The new computing method of internal force of piles under the Interaction of piles, soils and rigid cap [J]. Acta Scientiarum Naturalium Universitatis Sunyatseni, 2004, 43(4): 33-37.

    [3] 歐陽永忠,王瑞,陸秀平,等. VC、VB與FORTRAN的混合編程技術(shù)及其實現(xiàn)[J]. 海洋測繪, 2004, 24(1): 54-59. OUYANG Y Z, WANG R, LU X P, et al. On mixed-language programming and realization with VC, VB and Fortran [J]. Hydrographic Surveying and Charting, 2004, 24(1): 54-59.

    [4] 李學(xué)哲, 白云, 陳國新. Fortran 90與VB混合編程技術(shù)的研究與實現(xiàn)[J]. 蘇州科技學(xué)院學(xué)報(工程技術(shù)版), 2008, 21(4): 76-80. LI X Z, BAI Y CHEN G X. The research and implementation of VB and Fortran90 mixed-language programming technology [J]. J of University of Science and Technology of Suzhou (Engineering and Technology), 2008, 21(4): 76-80.

    [5] 何萌, 柴軍瑞. VB與FORTRAN混合編程的兩種方法及其比較[J]. 水電能源科學(xué), 2005(1): 60-62. HE M, CHAI J R. Two kinds of methods of mixing VB and Fortran in one program and their comparison [J]. Water Resources and Power, 2005(1): 60-62.

    [6] 畢蘇萍, 周振紅. Visual Fortran創(chuàng)建Win32 API式的DLL[J]. 計算機工程與設(shè)計, 2008, 29(18): 4868-4871. BI S P, ZHOU Z H. Creating DLL in accordance with win32 API in visual Fortran [J]. Computer Engineering and Design, 2008, 29(18): 4868-4871.

    [7] 顏國紅, 周振紅. 工程計算平臺CVF的應(yīng)用接口資源擴充[J]. 長江科學(xué)院院報, 2008, 25(4): 106-110. YAN G H, ZHOU Z H. How to extend API in engineering computation platform of CVF [J]. Journal of Yangtze River Scientific Research Institute, 2008, 25(4): 106-110.

    [8] INTEL CORP. Intel Fortran compiler 11.1 user and reference guides [M]. USA: Intel Corporation, 2009.

    [9] MICROSOFT CORP. Microsoft visual studio 2010 documentation [M]. USA: Microsoft Corporation, 2010.

    Mixed-language programming with Fortran and VB.NET

    HU Wenqing, ZHAN Jiemin

    (Department of Applied Mechanics and Engineering, College of Engineering, Sun Yat-sen University, Guangzhou 510275, China)

    Fortran language has high execution efficiency. It is widely used in the field of numerical calculation. And it has accumulated a lot of high-efficient and reliable source codes. For example, The Microsoft IMSL-Fortran Library can give powerful mathematical and statistical analysis. VB.NET is a fully object-oriented language. Compared against VB language, VB.NET is quicker and easier to develop a more powerful Windows program. Mixed-language programming of VB.NET calling Fortran through dynamic link library mode is studied. It gives the corresponding calling method for variable, string, array, structure and structure array. Also the typical examples are offered. It provides technical support for the development of software with both advantages of Fortran and VB.NET: high execution efficiency and quick and easy development ability.

    Fortran; VB.NET; mixed-language programming

    10.13471/j.cnki.acta.snus.2017.04.001

    2016-07-25 基金項目:廣東省協(xié)同創(chuàng)新與平臺環(huán)境建設(shè)專項(2014B090904066)

    胡文清(1987年生),男;研究方向:流體力學(xué);E-mail: emp_beren@163.com

    詹杰民(1963年生),男;研究方向:流體力學(xué);E-mail: stszjm@mail.sysu.edu.cn

    TP311

    A

    0529-6579(2017)04-0001-08

    猜你喜歡
    字符串數(shù)組調(diào)用
    JAVA稀疏矩陣算法
    電腦報(2022年13期)2022-04-12 00:32:38
    JAVA玩轉(zhuǎn)數(shù)學(xué)之二維數(shù)組排序
    電腦報(2020年24期)2020-07-15 06:12:41
    核電項目物項調(diào)用管理的應(yīng)用研究
    LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
    基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
    尋找勾股數(shù)組的歷程
    一種新的基于對稱性的字符串相似性處理算法
    利用RFC技術(shù)實現(xiàn)SAP系統(tǒng)接口通信
    依據(jù)字符串匹配的中文分詞模型研究
    VB數(shù)組在for循環(huán)中的應(yīng)用
    考試周刊(2012年88期)2012-04-29 04:36:47
    交城县| 友谊县| 齐齐哈尔市| 新建县| 江山市| 临泉县| 临澧县| 当雄县| 香河县| 郴州市| 泊头市| 商都县| 北川| 麟游县| 莆田市| 平潭县| 井冈山市| 大竹县| 富源县| 陆良县| 龙井市| 莫力| 沂南县| 双牌县| 顺义区| 阳春市| 翼城县| 达州市| 故城县| 洪雅县| 常熟市| 浑源县| 南丹县| 镇沅| 绍兴县| 高密市| 朔州市| 乌苏市| 陵川县| 巴南区| 喀喇沁旗|