以下は、Visual Fortran から Microsoft Visual C/C++ ルーチンを呼び出す例です。ソース中の注釈で、DLL の Visual C/C++ コードや C++ クラス中の C++ ルーチンに加える変更について説明しています。以下の説明では、Microsoft Visual C/C++ 6.0 以上がインストールされ、Visual Fortran V6.0 以降とビジュアル開発環境を共有していることを前提としています。
VC_Example2 という名前の主プログラム用の「Fortran Console Application」プロジェクトを作成します。この時、「An empty project」を選択してプロジェクトを作成します。
このプロジェクトで c_routine という名前の C/C++ ソース・ファイルを作成し (基本ファイル拡張子は .cpp)、以下のコードを入力します。
/*
* Fortran 主プログラムから呼び出される C ルーチン
*
* 整数入力引数をテキストに変換し、そのテキストを
* 文字列入力引数に追加し、文字列出力引数にその結果
* を保存します。
*/
#include <stdio.h>
/*
* このソースの拡張子が .cpp でクラスにルーチンを
* 置きたい場合、C++ の装飾名を使わないように以下
* の行を注釈にします。
* Fortran の !DEC$ ATTRIBUTES ALIAS:'xxx' 指示文
* で使用する正しい装飾外部名を決定するために
* DUMPBIN/SYMBOL xxx.obj を使用しなければなりません。
* ファイル拡張子が .c の場合、以下の行を削除します。
*/
extern "C"
/*
* このルーチンを DLL にする場合、以下の行を
* 注釈にします。
*/
// __declspec(dllexport)
void c_routine ( int int_arg,
char* input_text,
char* output_text )
{
sprintf(output_text,"%s%i ",
input_text,int_arg);
}
このプロジェクトで fmain という名前の Fortran 自由形式ソース・ファイルを作成し (基本ファイル拡張子は .f90)、以下のコードを入力します。
PROGRAM fmain
IMPLICIT NONE
! これは、C ルーチンを呼び出す
! Fortran 主プログラムの例です。
! 注釈のテキストは、DLL 中の
! C ルーチンの呼び出し方法と
! それが C++ ソースの場合の
! 呼び出し方法を示しています。
! 呼び出す C ルーチンのための
! インタフェースを宣言します。
!
INTERFACE
SUBROUTINE c_routine (int_arg, str_in,
str_out)
! 呼び出すものが C ルーチンであること
! を Fortran に告げます。
! これは、基本名付けおよび引数渡し規約
! を確立します。
!
!DEC$ ATTRIBUTES C :: c_routine
! DLL から c_routine を参照したい場合、
! DLLIMPORT 属性を追加します。最初の
! 感嘆符 (!) を取り除きます。
!
!!DEC$ ATTRIBUTES DLLIMPORT :: c_routine
! C ルーチンを C++ (.cpp ファイル拡張子)
! ソース・ファイルにし、'extern "C"
! 属性を持たせたくない場合、適切な C++ の
! 装飾名別名を指定しなければなりません。
! コマンド・プロンプトから
! DUMPBIN /SYMBOLS xxx.obj
! を実行してこの情報を得ます。この例の場合、
! 指示文は以下のようになります。
! 最初の感嘆符 (!) を取り除きます。
! 表示上の都合で3行に分割しています。
!
!!DEC$ ATTRIBUTES
! ALIAS:'?c_routine@@YAXHPAD0@Z'
! :: c_routine
INTEGER int_arg
CHARACTER*(*) str_in,str_out
! 隠された文字長を持たない CHARACTER 引数を
! 参照渡しで指定します。
!
!DEC$ ATTRIBUTES REFERENCE :: str_in, str_out
END SUBROUTINE c_routine
END INTERFACE
CHARACTER*80 OUTPUT_TEXT
INTEGER IN_ARG, OUTPUT_LEN
CHARACTER*80 INPUT_TEXT
! 下の C 接尾辞はヌル終了子を追加する
! ことを意味しています。
!
INPUT_TEXT = "Testing..."C
IN_ARG = 123
! c_routine を呼び出します。
! OUTPUT_TEXT にテキストを返します。
!
CALL c_routine (in_arg, input_text, output_text)
! 文字列中の後ろの空白を探すことで、
! OUTPUT_TEXT の文字長を検出します。
!
OUTPUT_LEN = INDEX(OUTPUT_TEXT," ")
IF (OUTPUT_LEN == 0) OUTPUT_LEN = 80
! コンソールに文字列を出力します。
!
WRITE (*,*) OUTPUT_TEXT(1:OUTPUT_LEN)
END
「Build」ボタンをクリックします。LIBCD が矛盾しているというリンク・エラーが発生した場合、「Project」メニューから「Settings」を選択し、表示される画面で「C/C++」タブをクリックし、「Code Generation」カテゴリを選択し、「Use Run-Time Library」で「Single-Threaded」を選択してください。そして、「OK」をクリックし、プロジェクトを再ビルドしてください。
プログラムを実行します。コンソール・ウィンドウに「Testing...00123」と表示されます。
C/C++ コードを DLL にしてビルドするには、C ルーチン用の別の DLL プロジェクトを作成します。上述の c_routine ファイルの「__declspec(dllimport)」の注釈と取り除き、DLL をビルドします。Fortran プロジェクトでは、!DEC$ ATTRIBUTES DLLIMPORT 指示文の注釈を取り除き (!DEC$ 文字列はそのまま残しておかなければならないことに注意してください)、DLL の .LIB をプロジェクトに追加し、ビルドします。プログラムを実行するには、.EXE があるディレクトリか PATH 環境変数で定義されているディレクトリのどこかにビルドした DLL がなければならないことに注意してください。
|