• ベストアンサー

FORTRANとC++の連動について

私は,Fortranを用いて解析の業務をしている,プログラム初心者です。 購入したのは,Intel Visual Fortran8.0(VF)ですが,Windows環境でコンパイルリンクするには,Microsoft Visual C++ .NET 2003(VC++)が必要ということで,こちらも購入しました。 普段は,Fortranのコンソールで ifort **.f といったコマンドでコンパイルリンクし,実行しているだけです。 これからは,VC++の方に移行していきたいと考えていますが,しばらくはFortranで作成したサブルーチンを有効活用したと考えています。 そこで,VC++ベースのメインプログラムからFortranのサブルーチンを呼び出すプログラムの作成方法,コンパイルリンク方法をご教授ください。よろしくお願いします。 (1)ソースにどう記述するか? void CMyDlg::OnBnClickedOk() { ここで,FORTRANのサブルーチンを呼び出したい。     Fortranなら call subroutine( a, b ) } (2)コンパイルするときは, Visual Studio開発環境で,コンパイル→実行で良いのか? それとも,あらかじめVC++とVFで.objファイルを作成する必要があるのか?

質問者が選んだベストアンサー

  • ベストアンサー
  • jirorin
  • ベストアンサー率100% (1/1)
回答No.3

まず、FortranとC++で1つのモジュールを作ることは出来ないと思います。CとFortranではランタイムライブラリが違うし、さらに言うとVF8はIntel製です。 やるなら、Fortranでライブラリ(staticまたはDynamic-link)を作り、C++からリンクするというやり方になると思います。 1.Visual C++で、MFCダイアログアプリを作成 2.新しいプロジェクトとして、Visual Fortranで、Static Libraryを追加。 3.test.fを以下の内容でFortranプロジェクトに追加 subroutine subsub( i, j) !DEC$ ATTRIBUTES C::subsub integer i, j !DEC$ ATTRIBUTES REFERENCE :: i, j c write(6,*) i,j i = i + j return end 4.個の関数を呼ぶC++ソースで extern "C"{ void subsub(int& i, int& j); }; void CcmainDlg::OnBnClickedOk() { int i, j; i = j = 1; subsub(i, j); TRACE("i=%d , j=%d\n", i,j); OnOK(); } 5.C++のプロジェクトの依存関係の設定でFortranプロジェクトをチェック ただ、Fortranの標準出力は使えません。 標準出力のライブラリはWindowsモジュールの ライブラリと共存できないはずです。 リンクエラーが出ます !DEC$ ATTRIBUTES のところが一番知りたいところだと思いますが スタートメニューの [Intel(R) Software Development Tools] [Intel(R) Fortran Compiler 8.0] [Documentation Index] を開いて、 Intel® Visual Fortran Compiler HTML Help Documentation で Programming with Mixed Languages Overview を検索すれば載っています。 この辺はVF6の頃から変わっていなくて わたしはVF6の日本語オンラインヘルプで読みましたが。

naetop
質問者

お礼

有難うございます。私もVF8の日本語ヘルプの該当個所を見つけることが出来ました。また,上記の方法で動作できました。 FORTRANにおける,!DEC$ ATTRIBUTESや C++における extern "C" のところがいまいち理解できていません。命名規則や参照渡しに関する事項だと思いますが。 現状では,FORTRANのサブルーチンには全く手を加えたくないので,FORTRANは,subroutine subsub(i,j)まま(!DEC~を追加していない)で下記のようにしております。 VC++における呼び出し部では, subsub(&i,&j); ヘッダー部では, extern "C" { void cdecl subsub(int*,int*); } として,うまく行ってます。 しかし,__stdcallを使うとうまく行かなかったりして, 路頭に迷っています。ご助言お願いします。

その他の回答 (3)

  • jirorin
  • ベストアンサー率100% (1/1)
回答No.4

呼出規約の、cdeclと_stdcallは別物です。アセンブラレベルで、どのレジスタを使うかとかというような規約です。さらに関数の名前付け規則でもあります。_stdcallは確か関数名の後に引数のバイト数が付きます。 Microsoftのコンパイラはデフォルトでcdeclです。 なので、確かに !DEC$ ATTRIBUTES C::subsub はいりません。 >FORTRANのサブルーチンには全く手を加えたくない 標準入出力は使えませんよ?

naetop
質問者

お礼

_stdcallだと@4などと追加されていました。 標準出力は,visual c++では使えませんでした。 コマンドラインでは使えました。 みなさんアドバイス有難うございます。 マスターまでには時間がかかりそうですが,FORTRANとVC++の連動が出来ましたので,これにて締め切りさせて 頂きます。

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.2

詳しくは両方のコンパイラを持っていないとわかりませんので、概要程度です。 まず、fortranとCでは引数の渡し方が異なります。 fortranはcall by referenceと呼ばれる方法で、 Cはcall by valueと呼ばれる方法です。 意味は調べてみてください。 具体的にはコンパイラによって違うかも知れませんが、fortranで整数を渡している部分は、Cでは整数のポインタとして引数が来ている考える必要があります。 多次元配列を使っている場合、並び順がCとFORTRANでは異なるので合わせる必要があります。 Cならメモリに[0][0],[0][1],[0][2]の順にならびますが、FORTRANでは(0,0),(1,0),(2,0)の順になります。 それとコンパイラ依存になりますが、アセンブラレベルで引数を渡す方法を同じにする必要があります。 おおまかに言えば、全てスタックを使う場合と特定のレジスタを優先して使い足らない場合スタックを使う場合があります。 実際にどうかは各コンパイラについて調べて、合わせる必要があります。また、プログラム中で指定可能かも知れません。 (VC++にはある。) あと、外部名を一致させる必要があります。 例えばCでfunc()という名まえの関数があってもこれはあくまで言語内部の名前で、他言語とのリンクを考える場合、リンカーが使う名前が問題になります。 確か、この場合は_func()という名前になったと思いますが。C++だと(オーバーロードがあるため)さらに複雑でおそらくそのまま使えませんから、Cインターフェイスを使用することになると思います。(extern "C") 逆にCからfunc()として呼び出すためには、_funcという名前にする必要があります。 fortranがどうなるかはコンパイラによります。多分、なんらかの手段は用意されていると思いますが。 多分、VFのマニュアルに説明があると思いますので調べてみてください。 初心者には難しいと思いますが。

naetop
質問者

お礼

有難うございます。理解できるよう調べていますが,まだうまくいきません。 おっしゃる通り,ソースコードが異なるFORTRANのサブルーチンを呼び出す場合は,ヘッダー部分に工夫が必要みたいですね。

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.1

VC++を使って出来たobjファイルがあるなら可能かもしれません。 場所は違うかもしれませんがvsv C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat を実行します。 cのソース(c.cpp)を改造します。 c.cppにプロトタイプ宣言を記述します。 void subroutine( int a, int b ); またよびだしたいところに、 subroutine( 10 , 20 ); を記述。 ※aとbが整数型(32bit)だった場合です。 cのソースをコンパイルします。 cl c.cpp /c これでc.objができます。 これをFortran8のobjとリンクします cl c.obj f.obj Intel Visual Fortran8.0については全く知らないので自信はありませんが。。。

naetop
質問者

お礼

アドバイス有難うございます。 試してみましたが,cl c.obj f.obj でリンクする際, に未解決の外部シンボルとしてエラーが発生致しました。 FORTRANのサブルーチンを認識していないようです。 VC++ #include <stdio.h> void subsub( int a, int b ); int main(void) { subsub( 10 , 20 ); return 0; } FORTRAN subroutine subsub( i, j) integer i, j write(6,*) i,j return end

関連するQ&A

専門家に質問してみよう