あなたは、 先の例の lseek
や dlseek
を呼び出す前に、 宣言する必要があります。 宣言は以下の 2
つの部分で構成されます:
関数の C 言語宣言です。 より一般的かつ移植性の高いものとしては、 C 言語の関数の宣言を含むファイルの C 言語スタイルの
#include
です。
パラメーターの Forth 型と、 C言語の関数に対応する Forth ワード名を宣言します。
前述の lseek
と dlseek
の宣言は以下のとおりです:
\c #define _FILE_OFFSET_BITS 64 \c #include <sys/types.h> \c #include <unistd.h> c-function lseek lseek n n n -- n c-function dlseek lseek n d n -- d
宣言の C言語部分は \c
という接頭辞が付けられ、 \c
の行の残りの部分は通常の C 言語のコードです。 C
言語の宣言の行は好きなだけ使用でき、 それ以降のすべての関数宣言で参照できます。
Forth 部分は、 c-function
で各インターフェイス・ワードを宣言し、 その後にワードの Forth 名と、 呼び出される C
言語の関数名と、 ワードのスタック効果が続きます。 スタック効果には、 任意の数のパラメーターのタイプ、 --
、 そして戻り値の「 1
つ」のタイプが含まれます。 可能なタイプは以下のとおりです:
n
単一セル整数
a
アドレス(単一セル)
d
2倍長セル整数
r
浮動小数点数値
func
C言語の関数へのポインター
void
値なし(void 関数の戻り値の型として使用)
可変個の引数(variadic)の C 言語の関数を扱うには、 あなたが使用したいパターンごとに 1 つの Forth ワードを宣言します。 例:
\c #include <stdio.h> c-function printf-nr printf a n r -- n c-function printf-rn printf a r n -- n
注意: C 言語の関数が可変個(variadic)の引数として宣言されている場合(または関数プロトタイプを提供していない場合)、 C 言語インターフェイスには変換先の C 言語の型がないため、 自動変換は行われず、 場合によっては移植性の問題が発生する可能性があることに注意してください。 C 言語の型キャストを波括弧({})で囲んで Forth 型の後に追加できます。 これにより、 例えば、 Forth ではスタック上に存在できない構造体を C 言語の関数へ渡す事も可能になります。
c-function printfll printf a n{(long long)} -- n c-function pass-struct pass_struct a{*(struct foo *)} -- n
C言語では左辺値(lvalues)の型キャスト(typecast)が許可されていないため、 この型キャストは戻り値には使用できません。
\c
( "rest-of-line" – ) gforth-0.7 “backslash-c”
C言語インターフェイスのC言語宣言の1行
c-function
( "forth-name" "c-name" "{type}" "–" "type" – ) gforth-0.7 “c-function”
Forth ワード forth-name を定義します。 Forth-name には指定されたスタック効果({type}
と type)があり、 C言語関数 c-name
を呼び出します。
c-value
( "forth-name" "c-name" "–" "type" – ) gforth-1.0 “c-value”
Forth ワード forth-name を定義します。 Forth-name には指定されたスタック効果(type)があり、
c-name
の C言語からの値を与えます(訳注: スタック効果の通り、 読み取りのみ)。
c-variable
( "forth-name" "c-name" – ) gforth-1.0 “c-variable”
Forth ワード forth-name を定義します。 Forth-name は c-name
のアドレスを返します。
この C言語インターフェイスが機能するために、 実行時に GCC を呼び出し、 動的リンク(dynamic linking)を使用します。 これらの機能が利用できない場合は、 lib.fs と oldlib.fs に、利便性と移植性に劣る他の C 言語インターフェイスが用意されています。 これらのインターフェイスはほとんど文書化されておらず、 また文書化された C言語インターフェイスとほとんど互換性がありません。 あなたが例を見たければ、 lib.fs インターフェイスの例が lib.fs にあります。