Visual Fortran アプリケーションの構造

Visual Fortran ハンドラがアプリケーションにどのように取り込まれるか,そして,自分独自のハンドラをどのように取り込むかを理解するためには,各アプリケーション・タイプがどのように構成されているかを理解する必要があります。以下の節では,様々なアプリケーション (プロジェクト) タイプに対するハンドラを説明しています。

Fortran Console アプリケーション

Fortran Console アプリケーションは,実際には,C main() 関数を提供する Visual Fortran 実行時システムを持つ,フードの下の C アプリケーションのようです。

Fortran Console アプリケーションのエントリ・ポイントは,C ライブラリーの mainCRTStartup() として指定されています (C 実行時ソースのモジュール crt0.c を参照)。これは,C 実行時システムを初期化し,C 実行時例外フィルタ (_XcptFilter()) を使用して Try/Except コンストラクトに Fortran 実行時システム main() をラップし,そして,実行時モジュール for_main.c の Fortran 実行時システム main() を呼び出します。簡単な書式では,以下のようになります。

	mainCRTStartup()
	{
	  C initialization code here
	  __try {
	    more initialization code here
	    mainret = main()	/* calls Fortran run-time main() */
	    exit(mainret)
	  } __except ( _XcptFilter() )
	    { _exit ( GetExceptionCode() ) }
	}

Fortran 実行時システムでは,main() は Fortran 実行時システムを初期化し (もし初期化されていなければ),例外で Fortran 実行時システムの基本ハンドラを呼び出すフィルタ式で MAIN__ (Fortran コードへのエントリ・ポイント) で Try/Except コンストラクトをラップし,そして,MAIN__ を呼び出します。Try/Finally コンストラクトをこれのすべてでラップします。そのため,実行時システムのクリーンアップは,プログラムが終了した時に (FOR_RTL_FINISH_ で) 行われます。簡単な書式では,以下のようになります。

	main()
	{
	  __try {
	    __try {
	      for_rtl_init()
	      MAIN__
	    } __except ( expression-invoking-fortran-default-handler )
	      { }
	  } __finally { for_rtl_finish() }
	}

Fortran コードでは,シンボル MAIN__ は実行時システムの main() ルーチンが呼び出すエントリ・ポイントです。MAIN__ は,更なる実行時初期化と検証を行うコードを持っています。たとえば,ユーザーが非基本の /fpe:0 オプションでコンパイルした場合,浮動小数点例外の設定/動作方法を実行時システムに伝えるために,FOR_SET_FPE の呼び出しが行われます。

Fortran QuickWin および Standard Graphics アプリケーション

(Fortran Standard Graphics を含む) Fortran QuickWin アプリケーションは,Visual Fortran が WinMain() 関数を提供する特殊化された Windows アプリケーションです。

QuickWin アプリケーションのエントリ・ポイントは,C ライブラリー・ルーチン WinMainCRTStartup() として指定されます (C 実行時ソースのモジュール crt0.c を参照)。これは,C 実行時初期化を行い,C 実行時例外フィルタ (_XcptFilter()) を使って Try/Except コンストラクトで Visual Fortran 定義の WinMain() をラップし,そして,Visual Fortran 定義の WinMain() ルーチンを呼び出します。簡単な書式では,以下のようになります。

	WinMainCRTStartup()
	{
	  C initialization code here
	  __try {
	    more initialization code here
	    mainret = WinMain()	/* calls CVF qwin library WinMain() */
	    exit(mainret)
	  } __except ( _XcptFilter() )
	    { _exit ( GetExceptionCode() ) }
	}

QuickWin ライブラリーでは,WinMain() は QuickWin に特化した初期化を行い,QWINForkMain で実行が開始される新しいスレッドを作成し,そして,動作を行うメッセージ・ループに入ります。メッセージ・ループは,例外が発生すると,Fortran 実行時システムの基本ハンドラを呼び出す Try/Except/Finally コンストラクトにラップされ,終了時に FOR_RTL_FINISH_ を呼び出します。他のスレッドで実行されている QWINForkMain は,順番に MAIN__ を呼び出す Fortran 実行時システム main() を呼び出します。簡単な書式では,以下のようになります。

	WinMain()
	{
	  Initialization code here
	  BeginThreadEx (..., QWINForkMain, ... )
	  __try {
	    __try {
	      the message loop...
	      for_rtl_finish()
	      return (msg.wParam)
	    } __except ( expression-invoking-default-fortran-handler )
	      { }
	  } __finally {
	    for_rtl_finish()
	    return (msg.wParam)
	  }
	}

QWINForkMain は以下に似ています。

	QWINForkMain()
	{
	  main()	:/* calls the CVF rtl main() which calls MAIN__ */
	  cleanup and exit...
	}

ルーチン main()MAIN__ は,Fortran Console アプリケーションで説明したものと同じです。

Fortran DLL アプリケーション

Fortran DLL は,一般的に他の主プログラムから呼び出されれる 1 つ以上のルーチンの集合です。そのため,DLL を呼び出すコードが作成した構造と環境で,ルーチンが実行されます。DllMain() 関数を通して DLL を初期化することができますが,主プログラムからアプリケーション全体の初期化を制御した方がよいでしょう。

DLL では,例外ハンドラを自動的に提供しません。プログラマが自分で提供するものを除いて,環境初期化も行いません。もちろん,主アプリケーションも Fortran で書かれている場合,そのアプリケーション・タイプで提供される Fortran 基本ハンドラを得ることができます。

Fortran Windows アプリケーション

Fortran Windows アプリケーションは,エントリ・ポイントとして WinMainCRTStartup() を持ちます。各ユーザーは,「Fortran Windows アプリケーションのコーディング要件」の説明に従ってコードを書きます。Fortran コードでの例が提供されているので,書き方をそれから知ることができます。コンパイラは,初期化コードを持つシンボル MAIN__ を生成しますが,MAIN__ を呼び出しません。実行時システムの main() に接続しないので,Visual Fortran 基本ハンドラにフックする Try/Except コンストラクタがありませんし,実行時システムの初期化とクリーンアップもありません。簡単な書式では,以下のようになります。

	WinMainCRTStartup()
	{
	  C initialization code
	  __try {
	    more initialization code
	    mainret = WinMain()	/* calls the user's WinMain() */
	    exit(mainret)
	  } __except ( _XcptFilter() )
	    { _exit ( GetExceptionCode() ) }
	}

Fortran コードは以下のようになります。

	integer(4) function WinMain( HANDLE, HANDLE, LPSTR, int )
	  ...
	  ! whatever Fortran the user codes here...
	  ...
	end