0.9.7におけるAPIの変更


(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

sizeに関する型

これまで、文字列や配列の大きさを気軽にintで扱ってきた部分がありました。Gaucheが産まれた頃、対象としたプラットフォームではintlongは大抵どちらも32bitだったんです。 けれども世界は変わりました。64bitアーキテクチャが普通になり、 32bitでは大きさを表すのに足りない場合が出てきました。

そこで、大きさを受け取る引数や戻り値の型を次の2つのいずれかにするように変更しました。

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を、srcdescriberには 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)

非推奨になったパラメータAPI

パラメータは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に残っているかもしれません。それらのファイルを削除しないと、 ビルド時にエラーになるでしょう。


Last modified : 2018/12/22 08:59:01 UTC