Fortran Module Wizard によって生成されたルーチンの呼び出し

Fortran 95/90 はオブジェクトをサポートしませんが,Fortran 95/90 モジュールを提供しています。モジュールとは大域的な名前の下にグループ化された宣言の組のことで,USE 文によって他のプログラム単位から使用することができます。

Fortran Module Wizard は 1 つまたは複数のモジュールを含んでいるソース・ファイルを生成します。モジュールに格納される情報の形式には次のものがあります。

ジャケット・ルーチンは,データ変換と低水準呼び出しの詳細を処理することで,Fortran から外部手続を簡単に呼び出せるようにするルーチンです。

Fortran Module Wizard はモジュールを使用することで,オブジェクトや DLL によって公開されているデータ構造と手続を 1 つの場所にカプセル化することができます。その後,プログラマはこれらの定義を複数の Fortran プログラムで共有することができます。

プログラムには,適切な USE 文に加えて,関数呼び出しやサブルーチン呼び出しを追加する必要があります。

Fortran Module Wizard によって生成されるルーチンは,Fortran から呼び出されることを念頭に置いて設計されています。これらのルーチンは,(Fortran から呼び出されることを念頭に置いて設計されていない) 適切なシステム・ルーチンを呼び出して,COM およびオートメーション・オブジェクトを使用するために必要なコーディングを単純化します。

Visual Fortran は,Fortran プログラマに,COM およびオートメーション機能の高水準の抽象化を提示する実行時ルーチンの組を提供しています。ウィザードが生成する Fortran インタフェースは,オートメーション・オブジェクトと COM オブジェクトの違いの大部分をわからないようにします。

指定したオプションに応じて,生成されたコードには次表に示したルーチンが含まれます。プログラマはこれらのルーチンを呼び出すことで,COM またはオートメーション・オブジェクトを使用することができます。

DFCOM ルーチン (COMxxxxx)
COMAddObjectReference オブジェクトのインタフェースに引用を追加します。
COMCLSIDFromProgID プログラマティック識別子を渡し,対応するクラス識別子を返します。
COMCLSIDFromString クラス識別子文字列を渡し,対応するクラス識別子を返します。
COMCreateObjectByGUID クラス識別子を渡し,オブジェクトのインスタンスを作成します。オブジェクトのインタフェースへのポインタを返します。
COMCreateObjectByProgID プログラマティック識別子を渡し,オブジェクトのインスタンスを作成します。オブジェクトの IDispatch インタフェースへのポインタを返します。
COMGetActiveObjectByGUID クラス識別子を渡し,現在活動状態のオブジェクトのインタフェースへのポインタを返します。
COMGetActiveObjectByProgID プログラマティック識別子を渡し,現在活動状態のなオブジェクトの IDispatch インタフェースへのポインタを返します。
COMGetFileObject ファイル名を渡し,ファイルを操作できるオートメーション・オブジェクトの IDispatch インタフェースへのポインタを返します。
COMInitialize COM ライブラリーを初期化します。他の COM または AUTO ルーチンを呼び出す前に,ライブラリーを初期化する必要があります。
COMIsEqualGUID 2 つの GUID が等しいかどうかを決定します。
COMQueryInterface インタフェース識別子を渡し,オブジェクトのインタフェースへのポインタを返します。
COMReleaseObject プログラムがオブジェクトのインタフェースへの引用の終了を通知します。
COMStringFromGUID GUID を渡し,対応する文字説明を返します。
COMUninitialize COM ライブラリーを非初期化します。これは最後に呼び出す COM ルーチンでなくてはなりません。
DFAUTO オートメーション・ルーチン (AUTOxxxxx)
AUTOAddArg 引数名と値を渡し,引数を引数並びデータ構造に追加します。
AUTOAllocateInvokeArgs AUTOInvoke に渡すことになる引数を保持する引数並びデータ構造を割り付けます。
AUTODeallocateInvokeArgs 引数並びデータ構造の割り付けを解除します。
AUTOGetExceptInfo メソッドが例外状態を返したときに,例外情報を取得します。
AUTOGetProperty プロパティの名前または識別子を渡し,オートメーション・オブジェクトのプロパティ値を取得します。
AUTOGetPropertyByID プロパティのメンバ ID を渡し,オートメーション・オブジェクトのプロパティ値を引数並びの第 1 引数として取得します。
AUTOGetPropertyInvokeArgs 引数並びデータ構造を渡し,オートメーション・オブジェクトの引数並びの第 1 引数で指定されたプロパティの値を取得します。
AUTOInvoke オブジェクトのメソッドの名前または識別子と,引数並びデータ構造を渡します。渡された引数を使ってメソッドを呼び出します。
AUTOSetProperty プロパティの名前または識別子と値を渡します。オートメーション・オブジェクトのプロパティ値を設定します。
AUTOSetPropertyByID プロパティのメンバ ID を渡し,オートメーション・オブジェクトの引数並びの第 1 引数を使ってプロパティの値を設定します。
AUTOSetPropertyInvokeArgs 引数並びデータ構造を渡し,オートメーション・オブジェクトの引数並びの第 1 引数で指定されたプロパティの値を設定します。

Visual Fortran サンプルとしては,Fortran Module Wizard の使い方を示すいくつかのプロジェクトが ...\DF98\SAMPLES\ADVANCED\COM フォルダにあります。次に例を示します。

DSLINES サンプルが使用する生成されたコードの例

DSLINES サンプルには,COM インタフェースを使って,この機能やその他の Microsoft ビジュアル開発環境機能を呼び出すコードが含まれています。

次のコードは,Fortran Module Wizard が ...\COMMON\MSDEV98\BIN\devshl.dll の COM タイプ情報から生成するコードの注釈付きのバージョンです。この COM タイプ情報は,Microsoft ビジュアル開発環境オブジェクト・モデルの最上位オブジェクトを記述しています。

	INTERFACE
!	ドキュメントをディスクに保存します。						
	INTEGER*4 FUNCTION IGenericDocument_Save($OBJECT, vFilename, &
	&					 vBoolPrompt, pSaved)		
	USE DFCOMTY
	INTEGER*4, INTENT(IN) :: $OBJECT		! オブジェクト・ポインタ
	!DEC$ ATTRIBUTES VALUE :: $OBJECT					
	TYPE (VARIANT), INTENT(IN) :: vFilename		! (省略可能な引数)		
	!DEC$ ATTRIBUTES VALUE :: vFilename
	TYPE (VARIANT), INTENT(IN) :: vBoolPrompt	! (省略可能な引数)
	!DEC$ ATTRIBUTES VALUE :: vBoolPrompt
	INTEGER*4, INTENT(OUT) :: pSaved		! Void			
	!DEC$ ATTRIBUTES REFERENCE :: pSaved
	!DEC$ ATTRIBUTES STDCALL :: IGenericDocument_Save
	END FUNCTION IGenericDocument_Save
	END INTERFACE
!	ルーチン・ポインタ								
	POINTER(IGenericDocument_Save_PTR, IGenericDocument_Save)

この例に関する注意

タイプ情報がメンバ関数を記述するコメントを提供する場合,そのコメントは手続が始まる前に置かれます。
手続への第 1 引数はつねに $OBJECT です。これはオブジェクトのインタフェースへのポインタです。残りの引数名はタイプ情報から決定されます。オブジェクトのインタフェースへのポインタを入手する方法については,「オブジェクトのインタフェースへのポインタの取得」を参照してください。
これは,引数の呼び出し規約を指定するために使用される ATTRIBUTE コンパイラ指示文の例です。
VARIANT は,任意の形式のオートメーション・データを格納できるデータ構造です。ここには,データの形式を識別する欄と,データ値を保持する共用体が含まれています。VARIANT 引数を使用することで,呼び出し側はメンバ関数が期待しているデータ型への変換が可能な任意のデータ型を使用することができます。
ほぼすべての COM メンバ関数は,HRESULT 型の状態を返します。このため,COM メンバ関数が出力を生成するときには,出力引数を使って値を返します。この例では,"pSaved" 引数はルーチン特有の状態値を返します。
COM メンバ関数のインタフェースは,ダイナミック・リンク・ライブラリー関数のインタフェースとよく似ていますが,1 つの大きな違いがあります。DLL 関数とは異なり,COM メンバ関数のアドレスは,プログラムのリンク時には不明です。このためオブジェクトのインタフェースへのポインタを実行時に取得し,これをもとにメンバ関数のアドレスを計算する必要があります。

次の例は,Fortran Module Wizard が "Save" 関数のために生成するラッパの注釈付き版を示しています。ラッパの名前は,対応するメンバ関数の名前の前に "$" の文字を付けたものです。

!	ドキュメントをディスクに保存します。
	INTEGER*4 FUNCTION $IGenericDocument_Save($OBJECT, vFilename, & 	
	&					  vBoolPrompt, pSaved)
	!DEC$ ATTRIBUTES DLLEXPORT :: $IGenericDocument_Save
	IMPLICIT NONE
	INTEGER*4, INTENT(IN) :: $OBJECT		! オブジェクト・ポインタ
	!DEC$ ATTRIBUTES VALUE :: $OBJECT
	TYPE (VARIANT), INTENT(IN), OPTIONAL :: vFilename
	!DEC$ ATTRIBUTES REFERENCE :: vFilename
	TYPE (VARIANT), INTENT(IN), OPTIONAL :: vBoolPrompt
	!DEC$ ATTRIBUTES REFERENCE :: vBoolPrompt
	INTEGER*4, INTENT(OUT) :: pSaved		! Void
	!DEC$ ATTRIBUTES REFERENCE :: pSaved
 
	INTEGER*4 $RETURN
	INTEGER*4 $VTBL					! インタフェース関数表	
	POINTER($VPTR, $VTBL)
	TYPE (VARIANT) :: $VAR_vFilename
	TYPE (VARIANT) :: $VAR_vBoolPrompt
	IF (PRESENT(vFilename)) THEN						
	  $VAR_vFilename = vFilename
	ELSE
	  $VAR_vFilename = OPTIONAL_VARIANT
	END IF
	IF (PRESENT(vBoolPrompt)) THEN
	  $VAR_vBoolPrompt = vBoolPrompt
	ELSE
	  $VAR_vBoolPrompt = OPTIONAL_VARIANT
	END IF
	$VPTR = $OBJECT					! インタフェース関数表	
	$VPTR = $VTBL + 84				! ルーチン表オフセットを追加します。
	IGenericDocument_Save_PTR = $VTBL
	$RETURN = IGenericDocument_Save($OBJECT, $VAR_vFilename, &
	&				$VAR_vBoolPrompt, pSaved)
	$IGenericDocument_Save = $RETURN
	END FUNCTION $IGenericDocument_Save

この例に関する注意

ラッパはメンバ関数インタフェースと同じ引数名を取ります。
ラッパは,インタフェース・ポインタと,インタフェースのタイプ情報に含まれるオフセットから,メンバ関数のアドレスを計算します。実装用語としてインタフェース・ポインタとは,"Interface Function Table" と呼ばれる関数ポインタの配列へのポインタを引用するポインタのことです。
COM または AUTO ルーチンの引数は省略可能です。ラッパは呼び出しの細部を処理し,呼び出しに含まれていない省略可能な引数を自動的に指定します。
"Save" メンバ関数のオフセットは 84 です。コードは計算されたアドレスを,前の例で宣言した関数ポインタ IGenericDocument_Save_PTR に代入した後に,関数を呼び出します。

DSLINES サンプルには,この機能やその他の Microsoft ビジュアル開発環境機能を,COM インタフェースを使って呼び出すコードが含まれています。

DSBUILD サンプルが使用する生成されたコード例

DSBUILD サンプルには,この機能やその他の Microsoft ビジュアル開発環境機能を,オートメーション・インタフェースを使って呼び出すコードが含まれています。

次の例は,...\COMMON\MSDEV98\BIN\devshl.dll にあるオートメーション・タイプ情報から Fortran Module Wizard が生成するコードの注釈付き版を示しています。

!	指定した構成ですべてのファイルを再ビルドします。
	SUBROUTINE IApplication_RebuildAll($OBJECT, Configuration, $STATUS)	
	!DEC$ ATTRIBUTES DLLEXPORT :: IApplication_RebuildAll
	IMPLICIT NONE
 
	INTEGER*4, INTENT(IN) :: $OBJECT		! オブジェクト・ポインタ
	!DEC$ ATTRIBUTES VALUE :: $OBJECT
	TYPE (VARIANT), INTENT(IN), OPTIONAL :: Configuration
	!DEC$ ATTRIBUTES REFERENCE :: Configuration
	INTEGER*4, INTENT(OUT), OPTIONAL :: $STATUS	! メソッド状態
	!DEC$ ATTRIBUTES REFERENCE :: $STATUS
	INTEGER*4 $$STATUS
	INTEGER*4 invokeargs
	invokeargs = AUTOALLOCATEINVOKEARGS()					
	IF (PRESENT(Configuration)) CALL AUTOADDARG(invokeargs, '$ARG1', &
	&					    Configuration, .FALSE.)
	$$STATUS = AUTOINVOKE($OBJECT, 28, invokeargs)				
	IF (PRESENT($STATUS)) $STATUS = $$STATUS				
	CALL AUTODEALLOCATEINVOKEARGS (invokeargs)				
	END SUBROUTINE IApplication_RebuildAll

この例に関する注意

手続への第 1 引数はつねに $OBJECT です。これは,オートメーション・オブジェクトの IDispatch インタフェースへのポインタです。手続への最後の引数はつねに $STATUS です。これは,メソッドの戻り状態を確認したいときに指定できる省略可能な引数です。IDispatch Invoke メンバ関数は HRESULT 型の状態を返します。HRESULT は 32 ビット値です。これは Win32 のエラー・コードと同じ構造を持っています。$OBJECT 引数と $STATUS 引数の間には,タイプ情報から決定されたメソッド引数の名前が含まれています。タイプ情報は引数の名前を含んでいないこともあります。この場合,Fortran Module Wizard は "$ARGn" という名前を作成します。
AUTOAllocateInvokeArgs は,ユーザーがメソッドに渡す引数を収集するために使われるデータ構造を割り付けます。AUTOAddArg はこのデータ構造に引数を 1 つ追加します。
AUTOInvoke は,引数並びを渡して,指定されたメソッドを呼び出します。これにより状態の結果が返されます。
呼び出し側が状態引数 (STATUS) を指定した場合,コードはそこに状態の結果をコピーします。
AUTODeallocateInvokeArgs は,引数並びデータ構造が使用するメモリーの割り付けを解除します。

...\DF98\SAMPLES\ADVANCED\COM フォルダの DSBUILD サンプルには,この機能や,その他の Microsoft ビジュアル開発環境機能を,オートメーション・インタフェースを使って呼び出すコードが含まれています。