11.4.1 C言語の出口関数の定義

ユーザ組み込み関数の機能を,C言語の出口関数中に記述します。

<この項の構成>
(1) C言語の出口関数の仕様
(2) C言語の出口関数の実装例

(1) C言語の出口関数の仕様

C言語の出口関数の仕様を次に示します。

(a) 形式

#include  "ETexit.h"

long  userfunc (long lArgNum, EXITARG *ppInArg[],
               EXITARG *pOutArg )

注:出口関数名(userfunc部分)には任意の名前を指定します。

(b) 引数
(入力)
lArgNum
ppInArg配列の要素の数が指定されます。
ppInArg
ユーザ組み込み関数の引数についての情報を格納するETEXITARG構造体のポインタ配列が指定されます。ETEXITARG構造体については,「(c) 説明」を参照してください。
(入出力)
pOutArg
ユーザ組み込み関数の戻り値についての情報を示す,ETEXITARG構造体のポインタが渡されます。
(c) 説明

ユーザ組み込み関数を使用した場合,トランスレータは,システム情報ファイル「ettrans.ini」の定義に従って対応する出口関数を呼び出します。

lArgNumが0の場合は,ppInArgにNULLが設定されます。

ETEXITARG構造体
ETEXITARG型は,入力となる引数の情報,及び出力となる戻り値の情報を格納する構造体であり,ヘッダファイル「ETexit.h」内で次のように定義されています。

typedef struct {
   long lType;
   ETEXITDATA data;
} ETEXITARG;

lTypeにはデータの型を表す値が入ります。「11.3.2 [Userfunc_Mapfunc]セクション」の「表11-2 ユーザ組み込み関数で使用する型」に示した型名をそのままマクロ定数として使用します。これらの値はヘッダファイル「ETexit.h」内で定義されています。
ETEXITDATA構造体は引数の値を格納するための共用体であり,ヘッダファイル「ETexit.h」内で次のように定義されています。

typedef union {
   long lNumber;
   double dNumber;
   void *pPtr;
   ETEXITDATASTRING edstring;
   ETEXITDATASTREAM edstream;
   ETEXITDATADTM eddtm;
   ETEXITDATAENVSTRING edenvstring;
} ETEXITDATA;

lNumberは,引数又は戻り値が整数型(ET_INT)の場合に使用します。dNumberは実数型(ET_REAL)の場合に使用します。pPtrはポインタ型(ET_PTR)の場合に使用します。
引数,及び戻り値のそれぞれが,ETEXITDATASTRING構造体は文字列型(ET_STRING),ETEXITDATASTREAM構造体はバイト列型(ET_STREAM),ETEXITDATADTM構造体は日付時刻型(ET_DTM),ETEXITDATAENVSTRING構造体は実行環境文字コード文字列型(ET_ENVSTRING)の場合に使用します。ヘッダファイルETexit.h内で次のように定義されています。

typedef struct {
   long lCode;
   long lLength;
   char *pszString;
} ETEXITDATASTRING;

typedef struct {
   long lLength;
   char *psStream;
} ETEXITDATASTREAM;

typedef struct {
   long lYear;        /* year */
   long lMonth;       /* month */
   long lDay;         /* day */
   long lHour;        /* hour */
   long lMinute;      /* minute */
   double dSecond;    /* second */
   char *pszZone;     /* zone string */
} ETEXITDATADTM;

typedef struct {
   long lErrCode;
   long lCode;
   char *pszString;
} ETEXITDATAENVSTRING;

lCodeには文字コードを表す定数が入ります。文字コードは,プレフィクス「ETEXIT_CODE_」を付けたマクロで表されます(例:ETEXIT_CODE_JIS8)。これらのマクロはETexit.h内に定義されています。
lLengthにはデータのサイズ(バイト数)が入ります。データが文字列の場合,終端NULLはサイズとして数えません。ETEXITDATASTRING構造体のpszString,及びETEXITDATASTREAM構造体のpsStreamにはそれぞれ文字列,バイト列を格納したメモリエリアへのポインタが入ります。文字列の場合に,終端NULLは付きません。
ETEXITDATADTM構造体のlYear~dSecondには,対応する日付時刻型のパート値が入ります。日付型や時刻型など,該当するパート値がない場合は,0を設定します。pszZoneには,日付時刻型のゾーン部文字列が終端NULL付きで入ります。ゾーン部を持たない場合はNULLです。ゾーン部文字列の文字コードは,Interschemaがサポートする実行環境のロケールに従います。Windowsの場合は,シフトJISです。
ETEXITDATAENVSTRING構造体のpszStringにはNULL終端文字列,lErrCodeには引数の文字列の実行環境のロケールに従った文字コードへの変換の成否を示すコードが入ります。lErrCode及びlCodeの値と,pszStringに格納される文字列の関係を次の表に示します。

表11-3 ETEXITDATAENVSTRING構造体のメンバの内容

項番lErrCode文字コード変換結果lCodepszString
10変換に成功した※1実行環境のロケールに従った文字コード実行環境のロケールに従った文字コードのNULL終端文字列です。
20x01000001変換時に不正文字コードを検出した※2実行環境のロケールに従った文字コード実行環境のロケールに従った文字コードのNULL終端文字列で,検出した不正文字コードをスペース文字へ置換したものです。
3-1変換に失敗したユーザ組み込み関数に渡された文字列の文字コードユーザ組み込み関数に渡された文字列に終端NULLを付加したものです。
注※1
ユーザ組み込み関数に渡された文字列が,最初から実行環境のロケールに従った文字コードの場合も含みます。
注※2
フォーマットの指定,又は実行時オプションで不正文字コードのスペース置換を禁止している場合,変換時に不正文字コードを検出したときは,項番3の結果が渡されます。

システム情報ファイルの[Userfunc_Option]セクションでUSE02IFオプションが指定されている場合,引数ppInArgの末尾にET_PTR型の情報を追加して渡します。ここにはETtrans2Exec関数で指定されたポインタを格納します。指定がない又はバージョン1の互換APIを使用している場合は,NULLが設定されます。また,lArgNumの値はシステム情報ファイルで定義した入力パラメタ数+1となります。

USE02IFオプションが指定されていない場合は,ET_PTR型のデータは追加設定しません。

pOutArgのデータは初期化された状態で出口関数に渡されます。ETEXITARG構造体のlTypeには,組み込み関数の戻り値型に対応した値があらかじめ設定されます。また,ETEXITDATA構造体のlNumber,dNumber,ETEXTITDATADTMのlYear~dSecondは,それぞれ0で初期化されます。

戻り値の型が文字列型の場合のpszString,バイト列型の場合のpsStream,日付時刻型の場合のpszZoneには,2,000バイト分確保したメモリのアドレスが設定されます。2,000バイトの領域は0で初期化されます。文字列,バイト列,日付時刻型のゾーン文字列を出力する場合は,出口関数内で2,000バイトに収まるようにデータを設定する必要があります。ゾーン文字列には終端NULLを付けてください。

異常終了時の戻り値(0以外の値)は出口関数内で任意に設定してかまいません。負の値を返した場合,トランスレータは変換処理を中止します。正の値を返した場合,トランスレータは変換処理を続行します。続行する場合,pOutArgとして出口関数からトランスレータに渡す値はリターン時のものになるので注意してください。エラー発生時の戻り値は,トランスレータのログとして出力されます。

(d) 戻り値
0
正常に終了しました。
>0
異常で終了しました。ただし,トランスレータの処理は続行します。
<0
異常で終了しました。トランスレータの処理を終了します。

(2) C言語の出口関数の実装例

C言語の出口関数の実装例を,整数型の場合,実数型で可変個引数の場合,文字列型の場合,日付時刻型の場合,及びUSE02IFオプションを使用した場合に分けて次に示します。