例 - 簡単な平均化関数
組み込み関数を 3GL プログラムとして定義
このセクションでは、組み込み関数をプログラムとして作成する際の手順を説明します。以下に示されているサンプルは非常に簡素なものですが、LANSA で組み込み関数がどのように利用されるのかの概要が理解できると思います。
シナリオ:これはユーザー定義の組み込み関数です。この組み込み関数を使って、システム値を取得します。
簡素な C プログラムです。このプログラムは、システム値の名前を渡し、システム値が返されます。
この名前は UD_AVERAGE です。
このサイトで次に利用可能な識別子は 413 です。
この組み込み関数は、 LANSA RDML 言語では以下のようにアクセスすることが可能です。
define field(#number1) type(*dec) length(7)
define field(#number2) type(*dec) length(7)
define field(#mean) type(*dec) length(7)
request fields(#number1 #number2)
use ud_average with_arg(#number1 #number2) to_get(#mean)
pop_up fields(#mean)
次は、UD_AVERAGE という名前の C のユーザー定義組み込み関数で、引数として、2 つの 10 進数を受け取り、その平均値を返します。
引数と返り値はすべて必須の値です。
この組み込み関数は平凡なもので、これを利用することもないかもしれませんが、まずは簡単な取り掛かりとして紹介します。
BIF 定義 (IBM i は DC@F47 ファイル/Windows は LX_F47 ファイル)
BIF名: | UD_AVERAGE |
|---|---|
一意の識別子: | 413 |
説明: | システム値の取得 |
呼び出しまたは実行: | C |
プログラム名: | U_BIF413 |
呼び出し間での終了: | N (Y <はい> または N <いいえ>) |
引数の数: | 2 |
戻り値の数: | 1 |
BIF 引数 (IBM i は DC@F47 ファイル/Windows は LX_F47 ファイル)
パラメータ 1
BIF名: | UD_AVERAGE |
|---|---|
パラメータタイプ | ARG |
パラメータシーケンス: | 1 |
パラメータ番号: | 1 |
パラメータ識別子: | A |
説明: | 最初の値 |
必須/任意: | R (R <必須> または O <任意>) |
パラメータタイプ: | N (A、N、または L) |
最小長: | 7 |
最大長: | 7 |
小数点以下最小桁数: | |
小数点以下最大桁数: | |
引き渡し長: | 10 |
引き渡す小数点以下桁数: | |
デフォルト: |
パラメータ 2
BIF名: | UD_AVERAGE |
|---|---|
パラメータタイプ | ARG |
パラメータシーケンス: | 2 |
パラメータ番号: | 2 |
パラメータ識別子: | B |
説明: | 2 番目の値 |
必須/任意: | R (R <必須> または O <任意>) |
パラメータタイプ: | N (A、N、または L) |
最小長: | 7 |
最大長: | 7 |
小数点以下最小桁数: | |
小数点以下最大桁数: | |
引き渡し長: | 10 |
引き渡す小数点以下桁数: | |
デフォルト: |
BIF 戻り値 (IBM i は DC@F47 ファイル/Windows は LX_F47 ファイル)
BIF名: | UD_AVERAGE |
|---|---|
パラメータタイプ | RET |
パラメータシーケンス: | 1 |
パラメータ番号: | 3 |
パラメータ識別子: | C |
説明: | 平均値 |
必須/任意: | R (R <必須> または O <任意>) |
パラメータタイプ: | A (A、N、または L) |
最小長: | 7 |
最大長: | 7 |
小数点以下最小桁数: | |
小数点以下最大桁数: | |
引き渡し長: | 256 |
引き渡す小数点以下桁数: |
次に、以下のようにデータを組み込み関数定義ファイルに入力します:
/* ================================================================ */
/* ============== ユーザー定義組み込み関数の定義 ================== */
/* ================================================================ */
/* */
/* 以下はユーザー定義組み込み関数の定義方法を示すサンプルです */
/* 例として提供されているだけであり、明示的にも暗黙的にも */
/* 何の保証もされません。 このコードをコピーする場合、 */
/* 導入当初もその後もいかなる時点においても */
/* 組み込み関数の導入および保守の責任は、コピーした開発者にあります。*/
/* */
/* ユーザー定義組み込み関数はパワフルな機能ではありますが */
/* ユーザー定義組み込み関数の利用により、アプリケーションの */
/* 保守、移植性、整合性、セキュリティやパフォーマンスなどに */
/* 影響が及ぶ可能性がありますが、その責任は開発者にあることを */
/* 忘れないでください。 */
/* */
/* ================================================================ */
/* */
/* ソース ファイル : U_BIF413.C */
/* エントリー ポイント名 : U_Builtin_413 */
/* リンク先 DLL 名 : U_BIF413.DLL */
/* 共有オブジェクト名 : u_bif413.O */
/* OS/依存性 : Yes/No */
/* */
/* 修正履歴 : */
/* */
/* タスクID 日付 説明 */
/* ======= ==== =========== */
/* */
/* ================================================================ */
#define U_BIF_FUNCTION U_Builtin_413
#define U_BIF_FUNCTION_NAME "U_Builtin_413"
#define U_BIF_DESCRIPTION "この組み込み関数の説明"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include "x_glodef.h"
#include "x_glousr.h"
#ifdef X_OPERATING_SYSTEM_WIN
#include <windows.h>
#endif
#include "x_funstr.h"
#include "x_funpro.h"
#include "x_bif000.h"
/*==================================================================*/
/* */
/* 引数 : pX_Ids - 標準 X_IDS システム定義 */
/* pX_Pro - 標準 X_PRO プロセス定義 */
/* pX_Fun - 標準 X_FUN ファンクション定義 */
/* pX_Bif - 標準 X_BIF 組み込み関数定義 */
/* X_Fld[: - 標準 X_FLD フィールド定義 */
/* X_List[: - 標準 X_LIST リスト定義 */
/* sInCount - 引き渡された引数の数 */
/* sInVec[: - 引数のベクター */
/* sRetCount - 戻り値の数 */
/* sRetVec[: - 戻り値のベクター */
/*==================================================================*/
X_VOID_FUNCTION U_BIF_FUNCTION ( U_BIF_STANDARD_PARAMETERS )
{
/* ------------------------------------------------------------- */
/* シャットダウン要求の処理 (通常はアクティビティは不要) */
/* ------------------------------------------------------------- */
if (U_BIF_SHUTDOWN_REQUEST)
{
U_BIF_SET_GOOD_RETURN
}
/* ------------------------------------------------------------- */
/* それ以外 (ELSE) は要求のアクティビティを実行 */
/* ------------------------------------------------------------- */
else
{
X_LONG lArg1;
X_LONG lArg2;
X_LONG lAverage;
/* ------------------------------------- */
/* 引数 1 を取得 (C の慣習では 0) */
/* 引数 2 を取得 (C の慣習では 1) */
/* そして、この 2 つの平均値を計算 */
/* ------------------------------------- */
U_BIF_GET_ARG_AS_LONG (0,lArg1)
U_BIF_GET_ARG_AS_LONG (1,lArg2)
lAverage = (lArg1 + lArg2) / 2;
/* ------------------------------------- */
/* 結果を値 1 に返す */
/* (C の慣習では 0) */
/* ------------------------------------- */
U_BIF_SET_RET_FROM_LONG (0, lAverage);
/* ----------------------------------------------- */
/* "正しい" 戻り値を設定 (オペレーティング レベル) */
/* ----------------------------------------------- */
U_BIF_SET_GOOD_RETURN
}
/* ------------------------------------------------------------- */
/* コントロールを呼び出し元に返す */
/* ------------------------------------------------------------- */
U_BIF_RETURN;
}
この例に関する注意点は以下の通りです。
- C マクロの多用について。U_BIF_xxxx 参照のすべてはヘッダーファイル(.H) X_BIF000.H に含まれているマクロへの参照です。
これらのマクロはコンパイル時に C コードに展開されます。可能なかぎり、組み込み関数と Visual LANSA 定義の間の"インターフェース"、もしくは呼び出しのインターフェースとして、これらのマクロを利用するようにしてください。こうすことで、将来変更があったとしても、アプリケーションを守ることができます。
U_BIF マクロは多数用意されています。全マクロの一覧は「提供の U_BIF マクロ」を参照してください。 - タイプ (例: X_LONG) を使ったローカル変数の定義について。この定義は標準のヘッダー・ファイル X_GLODEF.H に含まれており、Visual LANSA から提供されます。U_BIF に渡される変数は、必ず (マクロ定義に示された) これらのタイプを使って宣言する必要があります。
変数宣言
ポインター宣言
関係する実際の C タイプ
X_VOID
X_PVOID
Void
X_BOOL
X_PBOOL
Int
X_SHORT
X_PSHORT
Short
X_USHORT
X_PUSHORT
符号なし short
X_LONG
X_PLONG
Long
X_ULONG
X_PULONG
符号なしd long
X_LONGLONG
X_PLONGLONG
LONGLONG (Windows): 64 ビット 符号付き整数WATCOMC との使用は推奨されません。
X_DOUBLE
X_PDOUBLE
double
X_CHAR
X_PCHAR
char (1 文字のみ)
X_VCHAR
X_PVCHAR
char ( > NULL/文字列終端を伴う 1 つの文字)
X_LIST_COUNT
X_LIST_COUNT *
Long
- C の番号の設定規則の使用について。慣例では、多くの C オブジェクトはオフセット ("N" 個のものについては 0 から N-1) により番号が振られています。
この規則がすべての U_BIF マクロにも使われています。ですから、"引数の番号 3" というのは、実際は U_BIF マクロ内では番号 2 として参照されています。
一般的にこのアプローチにより、コーディングしやすくなります。例えば、このファンクションをよりジェネリックなものにして、2 から 20 までの番号を引数として受け取るようにします (0 で除算するテストが不要)。これを行うためには、ファンクションのボディを次のように変更する必要があります。
{
X_LONG lArgValue;
X_SHORT sTotalArgs;
X_SHORT sCurrentArg;
X_DOUBLE dTotal = 0;
U_BIF_GET_ARGUMENT_COUNT (sTotalArgs)
for (sCurrentArg = 0; sCurrentArg < sTotalArgs; sCurrentArg++)
{
U_BIF_GET_ARG_AS_LONG (sCurrentArg, lArgValue)
dTotal = dTotal + lArgValue;
}
lAverage = dTotal / sTotalArgs;
U_BIF_SET_RET_FROM_LONG (0, lAverage)
U_BIF_SET_GOOD_RETURN
}