コンテンツにスキップ

DLL機能関数リファレンス

ScideamFunc.dll が提供する機能関数の仕様です。第1引数 context には、scideamStart()scideamUpdate() など Scideam から呼び出されるユーザー関数に渡された context をそのまま指定します。

DLC 素子:ユーザーが作成した DLL を読み込んで動作する素子。ユーザーにより任意のユニークな名称を付けられる。

基本パターン

機能関数は ScideamFunc.dll を動的ロードして使用します。以下のようにファイルスコープの static 変数として関数ポインタを宣言し、scideamStart()LoadLibraryA + GetProcAddress によりまとめて取得、scideamStop() で解放するのが基本形です。

#include <stdbool.h>
#include <windows.h>

#define EXPORT __declspec(dllexport)

// 機能関数呼び出しに必要なコンテキストの定義
typedef void* SContext;

// 使用したい機能関数の定義
typedef double (*OutputFunc)  (SContext context, const char* sym, const char* type, const char* mode);
typedef void   (*SetParamFunc)(SContext context, const char* sym, const char* par, double val);

// ファイルスコープで関数ポインタを保持
static HMODULE      handle   = NULL;
static OutputFunc   s_output   = NULL;
static SetParamFunc s_setParam = NULL;

EXPORT bool scideamStart(SContext ctx) {
    handle = LoadLibraryA("ScideamFunc.dll");
    if (handle == NULL) return false;

    s_output   = (OutputFunc)  GetProcAddress(handle, "Output");
    s_setParam = (SetParamFunc)GetProcAddress(handle, "SetParam");
    return true;
}

EXPORT void scideamUpdate(SContext ctx) {
    const double v = s_output(ctx, "R", "V", "AVE");
    s_setParam(ctx, "R", "Value", v * v / 10.0);
}

EXPORT void scideamStop(SContext ctx) {
    if (handle) {
        FreeLibrary(handle);
        handle = NULL;
    }
}

以下の各関数の使用例では、この基本パターンに従って関数ポインタ(s_output など)が既に取得済みである前提で、関数呼び出し部分のみを示します。

Add / Get / Remove

void  Add   (SContext context, const char* key, void* obj);
void* Get   (SContext context, const char* key);
void* Remove(SContext context, const char* key);

DLC 素子ごとに紐づく領域に、任意のオブジェクトを保持する仕組みです。3 つの関数を組み合わせて使用します。

関数 役割
Add obj(ポインタ)を key で登録します。
Get key で登録されたオブジェクトを取得します。
Remove key で登録されたオブジェクトを削除し、そのポインタを返します。戻り値を free しないとメモリリークします。

scideamUpdate() のローカル変数は毎周期消えてしまうため、積分値・前回値・カウンタなど、解析サイクルをまたいで保持したい状態の格納先として利用します。保持されるのはポインタのみで、所有権・解放責任はユーザーコード側にあります。scideamStop() で必ず Remove したうえで解放してください。

typedef

typedef void  (*AddFunc)   (SContext context, const char* key, void* obj);
typedef void* (*GetFunc)   (SContext context, const char* key);
typedef void* (*RemoveFunc)(SContext context, const char* key);

使用例 1:積分値の保持

積分値や前回値のように単一のスカラーを保持したい場合は、double* を直接登録するのがシンプルです。

bool scideamStart(SContext ctx) {
    double* integ = (double*)malloc(sizeof(double));
    *integ = 0.0;
    s_add(ctx, "integ", integ);
    return true;
}

void scideamUpdate(SContext ctx) {
    double* integ = (double*)s_get(ctx, "integ");
    *integ += 1.0 / s_mainFreq(ctx);   // 前周期の積分値を継続使用
}

void scideamStop(SContext ctx) {
    free(s_remove(ctx, "integ"));
}

使用例 2:移動平均フィルタ

複数の状態を1つの構造体にまとめて DLC 素子ごとに保持します。

#define WINDOW 8
#define STATE_KEY "filter_state"

typedef struct {
    double buf[WINDOW];
    double sum;
    int    index;
    int    filled;
} FilterState;

bool scideamStart(SContext ctx) {
    FilterState* s = (FilterState*)malloc(sizeof(FilterState));
    memset(s, 0, sizeof(FilterState));
    s_add(ctx, STATE_KEY, s);
    return true;
}

void scideamUpdate(SContext ctx) {
    FilterState* s = (FilterState*)s_get(ctx, STATE_KEY);

    const double v = s_output(ctx, "R", "V", "AVE");
    s->sum -= s->buf[s->index];         // 古い値を捨てる
    s->buf[s->index] = v;
    s->sum += v;
    s->index = (s->index + 1) % WINDOW;
    if (s->filled < WINDOW) s->filled++;

    const double ave = s->sum / s->filled;
}

void scideamStop(SContext ctx) {
    free(s_remove(ctx, STATE_KEY));
}

AppVersion

const char* AppVersion(SContext context);

ScideamFunc.dll のバージョン文字列(例:"1.10.1")を返します。

typedef

typedef const char* (*AppVersionFunc)(SContext context);

使用例

bool scideamStart(SContext ctx) {
    s_error(ctx, s_appVersion(ctx));
    return true;
}

Error

void Error(SContext context, const char* mes);

ユーザー定義のエラーメッセージを Scideam のエラーハンドラへ通知します。

typedef

typedef void (*ErrorFunc)(SContext context, const char* mes);

使用例

void scideamUpdate(SContext ctx) {
    const double v = s_output(ctx, "R", "V", "AVE");
    if (v < 0) {
        s_error(ctx, "Negative voltage detected");
    }
}

ExportVar / ImportVar

void   ExportVar(SContext context, const char* varsym, double val);
double ImportVar(SContext context, const char* dlcsym, const char* varsym);

任意の値を他の DLC 素子から参照可能な形で公開 (ExportVar) し、他の DLC 素子が公開している値を取得 (ImportVar) します。DLC 素子内で同名の変数が既にある場合は値のみ更新されます。

引数 説明
varsym エクスポートされた変数シンボル
dlcsym エクスポート元 DLC 素子のシンボル(ImportVar)
val 公開する値(ExportVar)

ImportVardlcsym, varsym に対応する素子が見つからない場合は、DLC_RUNTIME でエラーが通知され解析中断します。

typedef

typedef void   (*ExportVarFunc)(SContext context, const char* varsym, double val);
typedef double (*ImportVarFunc)(SContext context, const char* dlcsym, const char* varsym);

使用例

void scideamUpdate(SContext ctx) {
    s_exportVar(ctx, "duty", duty);                     // 他の DLC 素子から参照できる形で公開

    const double duty_in = s_importVar(ctx, "DLC1", "duty");
    /* ... duty_in を使った計算 ... */
}

FilePath

const char* FilePath(SContext context);

現在読み込んでいる回路ファイル(cvt2)のパスを返します。

typedef

typedef const char* (*FilePathFunc)(SContext context);

使用例

bool scideamStart(SContext ctx) {
    s_error(ctx, s_filePath(ctx));
    return true;
}

GlobalSymbol / LocalSymbol

const char* GlobalSymbol(SContext context);
const char* LocalSymbol(SContext context);

自身の DLC 素子のシンボル(識別子)を返します。Scideam ではGlobalSymbolLocalSymbol の挙動に差はなく、どちらも同じ文字列(DLL 設定時に命名した局所シンボル)を返します。

戻り値のポインタが指す文字列は次の処理時点で寿命が尽きるため、保持して使い続ける場合は strcpy 等でローカルバッファへディープコピーしてください。

typedef

typedef const char* (*GlobalSymbolFunc)(SContext context);
typedef const char* (*LocalSymbolFunc)(SContext context);

使用例

void scideamUpdate(SContext ctx) {
    char sym[256];
    strcpy(sym, s_localSymbol(ctx));                    // 次の処理まで残す場合はディープコピー
    const double v = s_importVar(ctx, sym, "var");
}

IsSeriesAnalysis / IsUpdateAnalysis

bool IsSeriesAnalysis(SContext context);
bool IsUpdateAnalysis(SContext context);

現在の解析モードを判定します。

モード 判定関数 意味
連続解析 IsSeriesAnalysis() 前回解析の終了時状態を引継いで続行します。
更新解析 IsUpdateAnalysis() パラメータ変更後に再実行される解析です。

デスクトップアプリ では Waveform / FRA / Sweep / Power 解析を行う際、本解析の前に定常状態へ移行させるための解析が実行されます。本解析では、その定常状態と同じ状態になるように初期化するパラメータ更新がかかるため、本解析中は IsUpdateAnalysis()true になります。また、デスクトップアプリ を使用する限り IsSeriesAnalysis()true になるユースケースは存在しません。

ScideamPy を使用する場合は、update_parameter() を実行した後の解析で IsUpdateAnalysis()true となり、continue_analysis() を実行した後の解析で IsSeriesAnalysis()true になります。

typedef

typedef bool (*IsSeriesAnalysisFunc)(SContext context);
typedef bool (*IsUpdateAnalysisFunc)(SContext context);

使用例

bool scideamStart(SContext ctx) {
    if (!s_isUpdate(ctx)) {
        // something
    }
    if (!s_isSeries(ctx)) {
        // something
    }
    return true;
}

MainFrequency

double MainFrequency(SContext context);

メイン周波数 [Hz] を返します。

typedef

typedef double (*MainFrequencyFunc)(SContext context);

使用例

void scideamUpdate(SContext ctx) {
    const double dt = 1.0 / s_mainFreq(ctx);   // 1周期あたりの秒数
}

Output

double Output(SContext context, const char* sym, const char* type, const char* mode);

sym, type, mode で指定される素子の出力変数値を取得します。

引数 説明
sym "R" 素子のシンボル
type "V" 出力タイプシンボル
mode "AVE" 出力モードシンボル

mode に指定できる値は以下のとおりです。

意味
"AVE" 平均値
"MAX" 最大値
"MIN" 最小値
"INI" 初期値
"FIN" 最終値
"PKV" ピーク値

明示的に登録されていない出力を参照すると DLC_RUNTIME でエラーが通知され解析中断します。

typedef

typedef double (*OutputFunc)(SContext context, const char* sym, const char* type, const char* mode);

使用例

void scideamUpdate(SContext ctx) {
    const double v = s_output(ctx, "R", "V", "AVE");
    /* ... v を使った計算 ... */
}

Param / SetParam

double Param   (SContext context, const char* sym, const char* par);
void   SetParam(SContext context, const char* sym, const char* par, double val);

sym, par で指定される素子のパラメータ値を取得 (Param) または設定 (SetParam) します。 sym, par に対応する素子が見つからない場合は、DLC_RUNTIME でエラーが通知され解析中断します。 SetParam で設定する値の妥当性はユーザー側で判断してください。妥当でない値を設定した場合でも解析は続行され、正しくない解析結果になる場合があります。

typedef

typedef double (*ParamFunc)   (SContext context, const char* sym, const char* par);
typedef void   (*SetParamFunc)(SContext context, const char* sym, const char* par, double val);

使用例

bool scideamStart(SContext ctx) {
    target_power = s_param(ctx, "R", "Value");
    return true;
}

void scideamUpdate(SContext ctx) {
    const double v = s_output(ctx, "R", "V", "AVE");
    const double r = fmax(v * v / 10.0, 1e-3);        // 10W 負荷となる抵抗値
    s_setParam(ctx, "R", "Value", r);
}

Quit

void Quit(SContext context);

解析を中断します。

Quit は解析中断を「要求」するだけで、その場で処理を打ち切るわけではありません。呼び出し以降のコードも関数から抜けるまで通常どおり実行されます。

typedef

typedef void (*QuitFunc)(SContext context);

使用例

void scideamUpdate(SContext ctx) {
    if (fault_detected) {
        s_quit(ctx);        // 次サイクルで解析停止
    }
}

Time / TotalTime

double Time(SContext context);
double TotalTime(SContext context);

解析の経過時間を返します。

関数 意味
Time()(t) 1回の解析内での経過時間 [s]
TotalTime()(tt) 累積解析時間 [s]

単発解析では t == tt ですが、更新解析では t が毎回 0 リセットされるのに対し、tt は通算で増え続けます。

typedef

typedef double (*TimeFunc)(SContext context);
typedef double (*TotalTimeFunc)(SContext context);

使用例

void scideamUpdate(SContext ctx) {
    const double t  = s_time(ctx);
    const double tt = s_totalTime(ctx);
}