基本設定では,Visual Fortran は文字列の隠された文字長を引数として渡します。隠された文字長の引数は,文字列のアドレスの直後に符号なしの 4 バイト整数として,つねに値で渡されます。属性を使うと,文字列の基本の渡し方を変更することができます。次表に,渡される文字列の各種属性の効果を示します。
引数として渡される文字列の ATTRIBUTES オプションの効果
引数 | 基本設定 | C | STDCALL | C, REFERENCE | STDCALL, REFERENCE |
文字列 | 参照で渡される。文字長は値で渡される。 | 最初の文字が INTEGER(4) に変換され値で渡される。 | 最初の文字が INTEGER(4) に変換され値で渡される。 | 参照で渡される。文字長は値で渡される。 | 参照で渡される。文字長は値で渡される。 |
VALUE オプションが指定された文字列 | エラー | 最初の文字が INTEGER(4) に変換され値で渡される。 | 最初の文字が INTEGER(4) に変換され値で渡される。 | 最初の文字が INTEGER(4) に変換され値で渡される。 | 最初の文字が INTEGER(4) に変換され値で渡される。 |
REFERENCE オプションが指定された文字列 | 参照で渡される。文字長が指定されることもある。 | 参照で渡される。文字長はなし。 | 参照で渡される。文字長はなし。 | 参照で渡される。文字長はなし。 | 参照で渡される。文字長はなし。 |
次にこの表の重要な点を示します。
VALUE または REFERENCE 属性のない文字列が C または STDCALL ルーチンに渡されるときには,参照では渡されません。その代わりに,最初の文字だけが値によって渡されます。
VALUE オプションが指定された文字列が C または STDCALL ルーチンに渡されるときには,参照では渡されません。その代わりに,最初の文字の値だけが渡されます。
基本設定である ATTRIBUTES,ATTRIBUTES C, REFERENCE,または ATTRIBUTES STDCALL, REFERENCE が指定された文字引数は,次のように処理されます。
/iface:mixed_str_len_arg が設定されていると,文字列長は文字列の先頭アドレスの直後に,スタックに (値で) プッシュされます。
/iface:nomixed_str_len_arg が設定されていると,文字列長は他の引数の後に,スタックに (値で) プッシュされます。
基本設定である ATTRIBUTES を指定して参照で渡される文字引数は,次のように処理されます。
/iface:mixed_str_len_arg が設定されていると,文字列長は文字列の先頭アドレスの直後に,スタックに (値で) プッシュされます。
/iface:nomixed_str_len_arg が設定されていると,文字列長は呼び出し元の手続からは取得できません。
C の文字列はすべてポインタなので,C は,文字列が文字列長なしに参照によって渡されるものと期待します。さらに,C の文字列はヌルで終わりますが,Fortran の文字列はそうではありません。Fortran と C 間で文字列を渡す方法は基本的に 2 つあります。Fortran の文字列を C の文字列に変換するか,Fortran の文字列を受け付ける C のルーチンを書くかです。
Fortran の文字列を C に変換するには,文字列が文字長なしに参照で渡され,文字列の末尾にヌルが付くような属性の組み合わせを選択します。たとえば,ia32 システムでは次のようにします。
INTERFACE SUBROUTINE Pass_Str (string) !DEC$ ATTRIBUTES C, ALIAS:'_Pass_Str' :: Pass_Str CHARACTER*(*) string !DEC$ ATTRIBUTES REFERENCE :: string END SUBROUTINE END INTERFACE CHARACTER(40) forstring DATA forstring /'This is a null-terminated string.'C/
ia64 システムでは,最初の ATTRIBUTES 行は,先頭の下線が省略され,次のようになります。
!DEC$ ATTRIBUTES C, ALIAS:'Pass_Str' :: Pass_Str
この例は,Fortran の DATA 文で,文字列にヌル終端文字を使用する拡張を示しています (「文字定数中の C 文字列」を参照してください)。
DATA forstring /'This is a null-terminated string.'C/
C のインタフェースは次のようになります。
void Pass_Str (char *string)
C のルーチンで Fortran の文字列を受け取るには,C は文字列アドレスとともに文字長の引数が渡されることを念頭に置かなくてはなりません。次に例を示します。
! Fortran コード INTERFACE SUBROUTINE Pass_Str (string) CHARACTER*(*) string END SUBROUTINE END INTERFACE
C のルーチンは,2 つの引数が渡されると考えなくてはなりません。
void __stdcall PASS_STR (char *string, unsigned int length_arg )
このインタフェースは,隠された文字長の引数を処理しますが,ヌルで終わる C の文字列と,そうでない Fortran の文字列間での調整は依然として行わなくてはなりません。また,Fortran の文字列に割り当てられたデータが宣言された長さよりも短かった場合,Fortran の文字列には空白が充填されます。
Fortran と C の言語が混在したプログラミングでは,これらの文字列の違いを C のルーチンで処理するよりも,可能な限り C の文字列を採用することをお勧めします。C の文字列を使うべきもう 1 つの理由は,Win32 API と大部分の C ライブラリー関数がヌルで終わる文字列を受け付けるということです。
構文 CHARACTER*(*) を使って文字列を返す Fortran 関数は,隠された文字長の引数と,その文字列のアドレスを引数並びの先頭に格納します。
このような Fortran 関数呼び出しを実装する C の関数は,この隠された文字長の引数を明示的に宣言し,これが値を返すために使用する必要があります。C の戻り型は void です。ただし,文字列を返す関数は使わないようにする方が,エラーの発生を避けやすいでしょう。可能な限り,サブルーチンを使用するか,文字列をモジュールまたは大域変数に格納するようにしてください。
Visual Basic の文字列は,Fortran に対して値で渡さなくてはなりません。Visual Basic の文字列は,実際には長さと位置の情報を含んでいる構造体として格納されます。値によって渡すと,この構造体が参照解除され,Fortran が期待するように文字列の位置だけが渡されます。次に例を示します。
Basic コード:
Declare Sub forstr Lib "forstr.dll" (ByVal Bstring as String) DIM bstring As String * 40 Fixed-length string CALL forstr(bstring)
Fortran コード:
SUBROUTINE forstr(s) !DEC$ ATTRIBUTES STDCALL :: forstr !DEC$ ATTRIBUTES REFERENCE :: s CHARACTER(40) s s = 'Hello, Visual Basic!' END
Fortran コンパイラ指示文 !DEC$ ATTRIBUTES STDCALL は,Fortran に対して,Visual Basic の呼び出し側プログラムから隠された文字長の引数を期待しないように指示します。STDCALL は Fortran の名前を小文字にするので,Visual Basic プログラム中では名前を小文字で指定します。
MASM は,基本設定では文字列に文字列の長さもヌル文字も追加しません。文字列長を追加するには,次の構文を使用します。
lenstring BYTE "String with length", LENGTHOF lenstring
ヌル文字を追加するには,次のように手作業で追加します。
nullstring BYTE "Null-terminated string", 0