uCosminexus Interschema ユーザーズガイド
ユーザ組み込み関数の機能を,C言語の出口関数中に記述します。
C言語の出口関数の仕様を次に示します。
#include "ETexit.h" long userfunc (long lArgNum, EXITARG *ppInArg[], EXITARG *pOutArg ) 注:出口関数名(userfunc部分)には任意の名前を指定します。
ユーザ組み込み関数を使用した場合,トランスレータは,システム情報ファイル「ettrans.ini」の定義に従って対応する出口関数を呼び出します。
lArgNumが0の場合は,ppInArgにNULLが設定されます。
typedef struct { long lType; ETEXITDATA data; } ETEXITARG;
typedef union { long lNumber; double dNumber; void *pPtr; ETEXITDATASTRING edstring; ETEXITDATASTREAM edstream; ETEXITDATADTM eddtm; ETEXITDATAENVSTRING edenvstring; } ETEXITDATA;
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;
表11-3 ETEXITDATAENVSTRING構造体のメンバの内容
項番 | lErrCode | 文字コード変換結果 | lCode | pszString |
---|---|---|---|---|
1 | 0 | 変換に成功した※1 | 実行環境のロケールに従った文字コード | 実行環境のロケールに従った文字コードのNULL終端文字列です。 |
2 | 0x01000001 | 変換時に不正文字コードを検出した※2 | 実行環境のロケールに従った文字コード | 実行環境のロケールに従った文字コードのNULL終端文字列で,検出した不正文字コードをスペース文字へ置換したものです。 |
3 | -1 | 変換に失敗した | ユーザ組み込み関数に渡された文字列の文字コード | ユーザ組み込み関数に渡された文字列に終端NULLを付加したものです。 |
システム情報ファイルの[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として出口関数からトランスレータに渡す値はリターン時のものになるので注意してください。エラー発生時の戻り値は,トランスレータのログとして出力されます。
C言語の出口関数の実装例を,整数型の場合,実数型で可変個引数の場合,文字列型の場合,日付時刻型の場合,及びUSE02IFオプションを使用した場合に分けて次に示します。
/* * usermod.c - 整数型ユーザ出口関数の実装例 */ #include <stdlib.h> #include "ETexit.h" long usermod(long lArgNum, ETEXITARG *ppInArg[], ETEXITARG *pOutArg) { /* 余剰を求める */ long lArg1, lArg2; if (lArgNum != 2 || ppInArg == NULL) return -1; if (ppInArg[0] == NULL || ppInArg[0]->lType != ET_INT) return -2; if (ppInArg[1] == NULL || ppInArg[1]->lType != ET_INT) return -2; lArg1 = ppInArg[0]->data.lNumber; lArg2 = ppInArg[1]->data.lNumber; if (lArg2 == 0) return -3; pOutArg->data.lNumber = lArg1 % lArg2; return 0; }
/* * useraverage.c : 実数型可変個引数ユーザ関数の実装例 */ #include <stdlib.h> #include "ETexit.h" long useraverage(long lArgNum, ETEXITARG *ppInArg[], ETEXITARG *pOutArg) { /* 平均値を求める */ double dTotal = 0.0; int i; if (lArgNum < 1 || ppInArg == NULL) return -1; for ( i = 0; i < lArgNum; i++){ if (ppInArg[i] == NULL || ppInArg[i]->lType != ET_REAL) return -2; dTotal += ppInArg[i]->data.dNumber; } pOutArg->data.dNumber = dTotal/(double)lArgNum; return 0; }
/* * userisspace.c : 文字列型ユーザ関数の実装例 */ #include <stdlib.h> #include <string.h> #include "ETexit.h" long userisspace(long lArgNum, ETEXITARG *ppInArg[], ETEXITARG *pOutArg) { /* 文字列中のスペースをチェックする */ ETEXITDATASTRING *peds1, *peds2; long i; if (lArgNum != 1 || ppInArg == NULL) return -1; if (ppInArg[0] == NULL || ppInArg[0]->lType != ET_STRING) return -2; peds1 = &ppInArg[0]->data.edstring; if (peds1->lLength >= 2000) return -3; if (peds1->lCode != ETEXIT_CODE_SJIS) return -4; peds2 = &pOutArg->data.edstring; for (i = 0; i < peds1->lLength; i++) { if (peds1->pszString[i] != ' ') break; } if (i < peds1->lLength){ strncpy(peds2->pszString, peds1->pszString, peds1->lLength); peds2->pszString[peds1->lLength] = '\0'; } else { strcpy(peds2->pszString, "(space)"); } peds2->lLength = strlen(peds2->pszString); peds2->lCode = ETEXIT_CODE_SJIS; return 0; }
/* * userdtm.c : 日付時刻型ユーザ関数の実装例 */ #include <stdlib.h> #include <string.h> #include "ETexit.h" long userdtm(long lArgNum, ETEXITARG *ppInArg[], ETEXITARG *pOutArg) { /* 特定の日時を設定する */ pOutArg->data.eddtm.lYear = 2002; pOutArg->data.eddtm.lMonth = 2; pOutArg->data.eddtm.lDay = 15; pOutArg->data.eddtm.lHour = 12; pOutArg->data.eddtm.lMinute = 0; pOutArg->data.eddtm.dSecond = 0.0; strcpy(pOutArg->data.eddtm.pszZone, "+09:30"); return 0; }
/* * userPrintEnvstring.c : 実行環境文字コード文字列型とAPIからのポインタを使用したユーザ関数の実装例 */ #include <string.h> #include <stdio.h> #include "ETexit.h" /* 実行環境文字コード型引数で受け取った文字列を,APIから渡されたファイルに書き込む関数 */ long userPrintEnvstring(long lArgNum, ETEXITARG *ppInArg[], ETEXITARG *pOutArg) { ETEXITDATAENVSTRING *pEdEnvstr = NULL; ETEXITDATASTRING *peds = NULL; const char *cszFile = NULL; FILE *fp = NULL; if (lArgNum != 2 || ppInArg == NULL) return -1; if (ppInArg[0] == NULL || ppInArg[0]->lType != ET_ENVSTRING) return -2; if (ppInArg[1] == NULL || ppInArg[1]->lType != ET_PTR) return -3; pEdEnvstr = &ppInArg[0]->data.edenvstring; if (pEdEnvstr == NULL || pEdEnvstr->lErrCode == -1) return -4; else { /* 実行環境の文字コードは SJISを仮定 */ if (pEdEnvstr->lCode != ETEXIT_CODE_SJIS) return -5; } /* APIから渡されたファイル名を取り出す */ cszFile = (const char *)ppInArg[1]->data.pPtr; if (!cszFile) return -6; /* ファイルに引数で受け取った文字列を書き込む */ fp = fopen(cszFile, "w"); if (!fp) return -7; fprintf(fp, "%s", pEdEnvstr->pszString); if (fp) fclose(fp); /* ユーザ組み込み関数の戻り値には引数の文字列をそのまま渡す */ peds = &pOutArg->data.edstring; strcpy(peds->pszString, pEdEnvstr->pszString); peds->lLength = strlen(peds->pszString); peds->lCode = ETEXIT_CODE_SJIS; return 0; }
All Rights Reserved, Copyright (C) 2000, Information-technology Promotion Agency, Japan.
All Rights Reserved. Copyright (C) 2005, 2008, Hitachi, Ltd.
All Rights Reserved, Copyright (C) 1985-1998, Microsoft Corporation.