(For English version: API Changes in 0.9.7)
1.0に向けてAPIを整理するために、0.9.7でいくつかの非互換な変更を行いました。
全てのC拡張モジュールは再コンパイルされる必要があります。また、コードの変更が必要になるかもしれません。
新しいGaucheのヘッダはプリプロセッサシンボルGAUCHE_API_0_97
をdefineしているので、0.9.7より前と以降の両方に対応したい場合は次のようにして切り替えてください。
#if GAUCHE_API_0_97 /* 新たなAPIを使うコード */ #else /* 以前のAPIを使うコード */ #endif
これまで、文字列や配列の大きさを気軽にint
で扱ってきた部分がありました。Gaucheが産まれた頃、対象としたプラットフォームではint
とlong
は大抵どちらも32bitだったんです。
けれども世界は変わりました。64bitアーキテクチャが普通になり、
32bitでは大きさを表すのに足りない場合が出てきました。
そこで、大きさを受け取る引数や戻り値の型を次の2つのいずれかにするように変更しました。
ScmSize
: ssize_t
の別名
ScmSmallInt
: Schemeのfixnumで表現可能な数を格納できる型。fixnumはアーキテクチャのワードサイズから2bit少ない符号つき整数なので、この型は通常long
。
Schemeの文字列とベクタの大きさはfixnumで表せるものに制限しているので、Schemeオブジェクトの長さを扱う場合はScmSmallInt
を使っています。それ以外の大きさを表す場面ではScmSize
を使います。
文字列やベクタを扱うC APIを呼んでいる場合は、コードを変えなければならない可能性が高いでしょう。
特に、大きさを受け取るためにint*
を渡しているところでは、コンパイルエラーになります。
(ScmSize
引数にint
を渡しているところはあまり問題にはならないでしょう。)
以下は変更のあったC関数のリストです。
/* pre-0.9.7 */ /* 0.9.7 */ ScmObj Scm_ArrayToList( ScmObj Scm_ArrayToList( ScmObj *elts, ScmObj *elts, int nelts) ScmSize nelts) ScmObj Scm_AraryToListWithTail( ScmObj Scm_AraryToListWithTail( ScmObj *elts, ScmObj *elts, int nelts, ScmSize netls, ScmObj tail) ScmObj tail) ScmObj *Scm_ListToArray( ScmObj *Scm_ListToArray( ScmObj list, ScmObj list, int *nelts, ScmSize *nelts, ScmObj *store, ScmObj *store, int alloc) int alloc) int Scm_Length(ScmObj obj) ScmSize Scm_Length(ScmObj obj) ScmObj Scm_CopyStringWithFlags( ScmObj Scm_CopyStringWithFlags( ScmString *str, ScmString *str, int flags, u_long flags, int mask) u_long mask) const char *Scm_GetStringContent( const char *Scm_GetStringContent( ScmString *str, ScmString *str, u_int *psize, ScmSmallInt *psize, u_int *plen, ScmSmallInt *plen, u_int *pflags) u_long *pflags) ScmObj Scm_CStringArrayToList( ScmObj Scm_CStringArrayToList( const char **array, const char **array, int size, ScmSmallInt size, int flags) u_long flags) int Scm_DStringSize( ScmSmallInt Scm_DStringSize( ScmDString *ds) ScmDString *ds) ScmObj Scm_DStringGet( ScmObj Scm_DStringGet( ScmDString *ds, ScmDString *ds, int flags) u_long flags) const char *Scm_DStringPeek( const char *Scm_DStringPeek( ScmDString *ds, ScmDString *ds, int *size, ScmSmallInt *size, int *len) ScmSmallInt *len) void Scm_DStringPutz( void Scm_DStringPutz( ScmDString *ds, ScmDString *ds, const char *str, constr char *str, int siz) ScmSmallInt siz) int Scm_DStringTruncate( int Scm_DStringTruncate( ScmDString *ds, ScmDString *ds, int newsize) ScmSmallInt newsize) const uint8_t *Scm_GetBytes( const uint8_t *Scm_GetBytes( ScmObj str_or_vec, ScmObj str_or_vec, size_t *size) ScmSize *size) long Scm_ReadDigitsAsLong( long Scm_ReadDigitsAsLong( ScmPort *port, ScmPort *port, ScmChar ch, ScmChar ch, int radix, int radix, ScmChar *next, ScmChar *next, int *numread) ScmSize *numread) long Scm_ParseDigitsAsLong( long Scm_ParseDigitsAsLong( const char *buf, const char *buf, size_t len, ScmSize len, int radix, int radix, int *numread) ScmSize *numread) void Scm_Putz(const char *s, void Scm_Putz(const char *s, int len, ScmSize len, ScmPort *port) ScmPort *port) void Scm_PutzUnsafe(const char *s, void Scm_PutzUnsafe(const char *s, int len, ScmSize len, ScmPort *port) ScmPort *port) int Scm_Getz(char *buf, ScmSize Scm_Getz(char *buf, int buflen, ScmSize buflen, ScmPort *port) ScmPort *port) int Scm_GetzUnsafe(char *buf, ScmSize Scm_GetzUnsafe(char *buf, int buflen, ScmSize buflen, ScmPort *port) ScmPort *port)
いくつかの手続きで、引数を変更しています。実はこれらの関数は何年もの間、
GAUCHE_API_0_95
を定義すると新たな定義が有効になるようになっていたのですが、
そちらをデフォルトに切り替えました。
変更を受けた関数の一覧です。以前のコードから新たなAPIを呼ぶ場合、
flags
引数には0を、src
とdescriber
には
SCM_FALSE
を、そしてout
にはSCM_OBJ(SCM_CURERR)
を渡すと
同じ挙動になります。
/* pre-0.9.7 */ /* 0.9.7 */ ScmObj Scm_MakeMacro( ScmObj Scm_MakeMacro( ScmSymbol *name, ScmObj name, ScmObj transformer) ScmObj transformer, ScmObj src, ScmObj describer) ScmObj Scm_Raise(ScmObj exc) ScmObj Scm_Raise(ScmObj exc, u_long flags) ScmObj Scm_ReportError(ScmObj e) ScmObj Scm_ReportError(ScmObj e, ScmObj out) ScmObj Scm_VMThrowException( ScmObj Scm_VMThrowException( ScmVM *vm, ScmVM *vm, ScmObj exc) ScmObj exc, u_long flags)
パラメータは2層で実装されています。C APIは単純なスレッドローカルストレージを提供し、 Scheme層でその上にフィルタ手続き等を含めた完全なパラメータオブジェクトが実装されます。 この2層を明確に区別するため、C層のそれをScmPrimitiveParameterと呼ぶことにして、 APIも新しくしました。
以前のAPIもしばらくはサポートしますが、できるだけ早く新たなAPIに移行してください。
以前のAPI:
void Scm_DefinePrimitiveParameter(ScmModule *mod, const char *name, ScmObj initval, ScmParameterLoc *location); ScmObj Scm_ParameterRef(ScmVM *vm, const ScmParameterLoc *loc); ScmObj Scm_ParameterSet(ScmVM *vm, const ScmParameterLoc *loc, ScmObj val); ScmObj Scm_InitParameterLoc(ScmVM *vm, ScmParameterLoc *loc, ScmObj initval);
新たなAPI:
ScmPrimitiveParameter *ScmPMakePrimitiveParameter(ScmClass *klass, ScmObj name, ScmObj initval, u_long flags); ScmPrimitiveParameter *Scm_BindPrimitiveParameter(ScmModule *mod, const char *name, ScmObj initval, u_long flags); ScmObj Scm_PrimitiveParameterRef(ScmVM *vm, const ScmPrimitiveParameter *p); ScmObj Scm_PrimitiveParameterSet(ScmVM *vm, const Scm_rimitiveParameter *p, ScmObj val);
Boehm GCは以前、動的リンクされるオブジェクトについてデータ領域をコードで
登録してやる必要があり、Gaucheはそのために小さなファイル(*_head.c
と
*_tail.c
)を、gauche-config --fixup-extension
コマンドによってビルド時に生成していました。
しかし、Boehm GCがデータ領域を自動で登録するようになってもうずいぶん経つので、
gauche-config --fixup-extension
機能もやめることにしました。
gauche-config
コマンドはその引数を受け付けますがファイルは生成しません。
gauche-package generate
によってコピーされるテンプレートファイルから、
*_head.c
と*_tail.c
への参照はずっと昔に削除されています。
けれども、C拡張がもっと昔に作られたものであった場合、それらのファイルへの参照が
Makefile
に残っているかもしれません。それらのファイルを削除しないと、
ビルド時にエラーになるでしょう。