こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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ファイルを作成する必要があるのか?

投稿日時 - 2005-03-31 22:25:20

QNo.1303644

困ってます

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

まず、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の日本語オンラインヘルプで読みましたが。

投稿日時 - 2005-04-12 15:29:26

お礼

有難うございます。私も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を使うとうまく行かなかったりして,
路頭に迷っています。ご助言お願いします。

投稿日時 - 2005-04-13 13:01:44

ANo.3

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

呼出規約の、cdeclと_stdcallは別物です。アセンブラレベルで、どのレジスタを使うかとかというような規約です。さらに関数の名前付け規則でもあります。_stdcallは確か関数名の後に引数のバイト数が付きます。

Microsoftのコンパイラはデフォルトでcdeclです。
なので、確かに
!DEC$ ATTRIBUTES C::subsub
はいりません。

>FORTRANのサブルーチンには全く手を加えたくない
標準入出力は使えませんよ?

投稿日時 - 2005-04-13 16:33:12

お礼

_stdcallだと@4などと追加されていました。
標準出力は,visual c++では使えませんでした。
コマンドラインでは使えました。

みなさんアドバイス有難うございます。
マスターまでには時間がかかりそうですが,FORTRANとVC++の連動が出来ましたので,これにて締め切りさせて
頂きます。

投稿日時 - 2005-04-15 20:31:32

ANo.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のマニュアルに説明があると思いますので調べてみてください。
初心者には難しいと思いますが。

投稿日時 - 2005-04-03 10:32:18

お礼

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

投稿日時 - 2005-04-05 08:40:41

ANo.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については全く知らないので自信はありませんが。。。

投稿日時 - 2005-04-01 08:22:39

お礼

アドバイス有難うございます。
試してみましたが,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

投稿日時 - 2005-04-04 08:59:33

あなたにオススメの質問