Fortran與C/C++的混合開發。。。
來源:互聯網
上載者:User
最近在把一個Fortran的程式封成模組整合進一個C++的平台中。平生第一次做fortran,也算是第一次正二八經的做二進位的混合開發。簡單寫一些,算為前一段工作做個總結。。。
Fortran90與C++的整合,可以基於靜態連結。就是都產生obj,然後link在一起。當然也可以是動態連結的,把Fortran打成dll,然
後在C++中調用(windows下...)。當然,這都不會是本質性的問題,你可以根據需求自行抉擇。在不同二進位模組中互調,更為關鍵的是ABI。說
英文的和說中文的總不能和諧的打成一片,要在一塊玩就需要一些共同的語言。。。
Calling Conventions在這裡顯得很重要。首先就是Naming
conventions,Fortran和C++的函數名解析往往是不一樣的。同樣你取名叫functionA的,在C++裡面(extern
"C")編譯完了可能叫functionA_,可到了fortran裡,可能會叫_functionA@4。當然,這個問題並不可怕,查一下編譯器的手
冊,此問題即可迎刃而解。。。
然後是Stack considerations的問題,也就是說函數棧是由調用方管理還是被呼叫者管理,有興趣的可以看下這裡,同時在fortran中,參數的預設傳遞方式不同,它預設通過傳址來進行傳遞,這一點需要注意。。。
最後,最麻煩的問題是Argument passing
protocol,一個fortran的資料在C++中應該怎麼表示呢?基礎資料型別 (Elementary Data Type)這都還好,但數組呢?自訂資料類型呢?在高層一些的語言裡,我們根
據序列化的方式,自動將參數序列化和還原序列化進行資料轉換,一切都比較水到渠成。但基於二進位的介面,調用的基礎只是棧的完全符合,一點點差池對會繆之千
裡。在fortran裡,數組是列優先的,這正與C++相反,需要注意。而更噁心的是,fortran的數組及其強大,可以從任何腳標起,其間隔可以是任
意的,於是乎在intel的編譯器下,一個普通的一維數組的指標,需要佔用32個位元組的空間。所有這些,都導致參數的傳遞在此類開發中成為最脆弱的環節。
它們彼此只是靠著棧中資訊的一致性依偎在一起,一點點編譯器的改動(或者用了一個其他的編譯器...),或者是兩邊程式資料結構的改動(對於自訂類型而
言...),都可能導致崩潰性的後果。解決這個問題,需要依靠在設計層面上解決。需要傳遞複雜結構的介面都不要用,用一系列方法的調用來替代單一的方法,
將簡單的資料依賴轉換成為介面定義的依賴。因為基礎資料型別 (Elementary Data Type)總是像黃金一樣堅挺,而複雜類型資料的解析總是像股票那般不靠譜。所以我們的原則是,只選簡
單,不選複雜。。。
當你做這樣一件工作的時候,官方的手冊和範例程式碼是你最好的幫手,而不要簡單的依靠問人或Google一下來解決問題。因為別人涉及到的問題可能和你的不
完全一致,而一點點不一樣可能就使得結果差的很遠了。這也體現出一個人解決一個新的問題的方法了。對我而言,我會把所有可能用到的手段和所需的資料都羅列
一下,儘可能的詳盡些。然後依照是繞過問題還是直面問題的差別分成兩類,先考慮繞過。如果覺得代價可接受,也可以一勞永逸的話,那麼先繞過再說,因為畢竟
是一個新問題,解決和繞過相比通常是難度更大。如果不能繞過,那麼就將你所有的手段按照可靠性排個序,通常,源碼總是比文檔可靠,而文檔有總比搜來的資料
可靠。如果一樣可靠度的手段,就需要考慮一下它們實施的簡單程度了,比如讀文檔(日文文檔除外,我已經被噁心夠嗆了...)也許會比看源碼簡單一些,那麼
先看看文檔再說。總之,我個人覺得可靠度比簡單性總會更重要一些,如果一些手段,比如從網上簡單搜來的方法,你覺得不可靠,那麼就不要先實施,往往是繞了
半天,你發現你又回到了原點。。。