
この記事では、引数をインジケーター(
part1 、
part2 )に接続する方法を説明します。 MetastockプログラムのMSXダイナミックライブラリDLLの引数には、MSXNthArgとMSXNthCustomStringの2つのユーティリティ関数があります。
引数
MSXNthArgは、各引数の初期化中に呼び出されます。各外部関数には引数があります。
BOOL __stdcall MSXNthArg (int a_iNthFunc, int a_iNthArg, MSXFuncArgDef *a_psFuncArgDef)
どこで
•a_iNthFunc-外部関数のインデックス。
•a_iNthArgは、この関数の引数のインデックスです。
•a_psFuncArgDef-ユーザーが外部関数の引数に関する情報を入力するために使用されるMSXFuncArgDefデータ構造へのポインター。
関数は以下を返します。
•すべてが正しく、MSX_SUCCESS
•エラーが発生した場合のMSX_ERROR。
すべての引数は4つのタイプに分けられます。
•MSXDataArray-データ配列
•MSXNumeric-番号、
•MSXString-文字列、
•MSXCustom-カスタム。
引数を使用する場合、ユーザーはそのタイプと名前を指定する必要があります。 MSXCustom型の引数は特定のセットであり、そのメンバーをカスタム引数と呼びます。 引数のタイプがMSXCustomの場合、カスタム引数の数も指定する必要があります。 つまり、引数を記述するときに、MSXNthArgに関数を記述します
非MSXCustomタイプの場合:
a_psFuncArgDef->iArgType = MSXDataArray;
MSXCustomタイプの場合:
a_psFuncArgDef->iArgType = MSXCustom; a_psFuncArgDef->iNCustomStrings = 8;
MSXNthCustomStringは、カスタム引数を担当します。
BOOL __stdcall MSXNthCustomString (int a_iNthFunc, int a_iNthArg, int a_iNthString, MSXFuncCustomString *a_psCustomString)
どこで
•a_iNthFunc-外部関数のインデックス。
•a_iNthArgは、この関数の引数のインデックスです。
•a_iNthString-カスタム引数のインデックス。
•a_psFuncArgDef-外部関数のカスタム引数に関する情報をユーザーに入力するために使用されるMSXFuncCustomStringデータ構造へのポインター。
この関数は、前のものと同じ値を返します。
カスタム引数は、文字列識別子のペアですMSXNthCustomString関数は、文字列と数値識別子(ID)の対応を設定します。 外部関数では、カスタム引数はIDによって呼び出されます。 カスタム引数の定義に使用される文字列は、英数字のみで構成する必要があります。 スペースと特殊文字は使用できません。 カスタム引数は大文字と小文字を区別しません。
各タイプの引数の数は10を超えることはできません。 関数と引数には0から番号が付けられることを忘れないでください。
例外
Metastockのクラッシュを回避するには、各外部関数に例外処理を追加する必要があります。 例外は次のとおりです。
•引数の数が無効です。
•着信(計算に使用)配列がMetastock標準に準拠していません(パート2を参照)
•引数を受け取っていない、
•引数が真ではない、
•出力(計算結果)配列がMetastock標準を満たしていません。
これらの各状況は、次の一般的な形式で処理します。
if ( , , ) { strncpy (a_psResult->szExtendedError, "Error: ", sizeof(a_psResult->szExtendedError)-1);
例外を処理するために、いくつかの追加機能を追加しました。
例
次の例では、加算を処理する4つのインジケーターを作成しました。 各インジケータには2つの引数があります。1つは配列、もう1つは4つのタイプのうちの1つです。 前半で約束したように、一連のステップを描きました。
Visual Studioで、MSXStruc.h、Add.cpp、Add.defの3つのファイルでプロジェクトを作成します。 ライブラリの名前はAdd.dllになります。
ステップ1-ヘッダーとエクスポートコード #include <string.h> #include <stdlib.h> #include <math.h> #include <float.h> #include <tchar.h> #include "MSXStruc.h" #define DLL_EXPORT extern "C" __declspec(dllexport)
ステップ2-変更可能なパラメーターここには、ユーザーが変更可能な関数と引数のパラメーターがすべて登録されています。
ステップ3-初期化関数ここでは、MSXInfo、MSXNthFunction、MSXNthArg、MSXNthCustomStringの4つの関数について説明します。
ステップ4-追加機能ここで、例外を処理するために必要な関数を書きます。
コード #define MSXMax(a,b) (((a) > (b)) ? (a) : (b)) #define MSXMin(a,b) (((a) < (b)) ? (a) : (b)) double ForceFloatRange (double a_lfDbl) { if (a_lfDbl > 0.0) { a_lfDbl = MSXMin (a_lfDbl, double(FLT_MAX)); a_lfDbl = MSXMax (a_lfDbl, double(FLT_MIN)); } else { if (a_lfDbl < 0.0) { a_lfDbl = MSXMax (a_lfDbl, double(-FLT_MAX)); a_lfDbl = MSXMin (a_lfDbl, double(-FLT_MIN)); } } return a_lfDbl; } /* MSXArray - MetaStock. MSXDataRec . , MSXDataRec. , , Metastock BasicData, . , , MetaStock'. */ BOOL MSXArray(const MSXDataRec *BasicData, const MSXDataInfoRec *ArgData) { if (ArgData->iFirstValid < 0) return FALSE; if (ArgData->iLastValid < 0) return FALSE; if (ArgData->iLastValid < ArgData->iFirstValid) return FALSE; if (ArgData->iFirstValid < BasicData->sClose.iFirstValid) return FALSE; if (ArgData->iLastValid > BasicData->sClose.iLastValid) return FALSE; return TRUE; }
ステップ5-外部機能fan1は2つのデータ配列(
ExtFml( "Add.fan1"、DA1、DA2) )を要約します。
この関数には2つの引数があり、両方ともデータの配列です。
fan1 DLL_EXPORT BOOL __stdcall fan1 (const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult) { int i = 0;
fan2は、データ配列と番号(
ExtFml( "Add.fan2"、DA1、Numeric) )を要約します。
この関数には2つの引数があり、1つはデータ配列、もう1つは数値です。
fan2 DLL_EXPORT BOOL __stdcall fan2 (const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult) { int i = 0;
fan3は、文字配列で指定されたデータ配列とデータ配列を要約します
(
ExtFml( "Add.fan3"、DA1、DAStr) )。
この関数には2つの引数があります。1つはデータ配列、もう1つは文字列です。
fan3 DLL_EXPORT BOOL __stdcall fan3 (const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult) { int i = 0; int iMinRecords = a_psBasic->sClose.iFirstValid; int iMaxRecords = a_psBasic->sClose.iLastValid; const MSXDataInfoRec *l_psInput1; l_psInput1 = a_psArrayArgs->psDataInfoRecs[0];
fan4は、データ配列とカスタム引数で定義されたデータ配列を要約します
(
ExtFml( "Add.fan4"、DA1、DACust) )。
この関数には2つの引数があり、1つはデータの配列、もう1つはMSXCustom型の引数です。
fan4 DLL_EXPORT BOOL __stdcall fan4 (const MSXDataRec *a_psBasic, const MSXDataInfoRecArgsArray *a_psArrayArgs, const MSXNumericArgsArray *a_psNumericArgs, const MSXStringArgsArray *a_psStringArgs, const MSXCustomArgsArray *a_psCustomArgs, MSXResultRec *a_psResult) { int i = 0; int iMinRecords = a_psBasic->sClose.iFirstValid; int iMaxRecords = a_psBasic->sClose.iLastValid; const MSXDataInfoRec *l_psInput1; l_psInput1 = a_psArrayArgs->psDataInfoRecs[0];
ステップ6-DEFファイル以下は私のプロジェクトのDEFファイルの例です。
DEFファイルは個別のテキストファイルであり、プロジェクトと同じ名前にする必要があります。
Add.def LIBRARY Add EXPORTS MSXInfo MSXNthFunction MSXNthArg MSXNthCustomString fan1 fan2 fan3 fan4
私の記事で、Metastockプログラム用の動的MSX DLLをアクセシブルな方法で構築する原理を説明できたことを願っています。