ldstr.dll :初期化のタイミング
floatex_ldstr_term 以外の ldstr 系の関数は、初回実行時に DLL の検索や読み込み等の初期化処理を行います。初期化に成功すると、続けて ldstr 系関数を呼び出しても初期化処理は行いません。しかし、最初の初期化に失敗している場合は、二回目以降の呼び出しでも初期化を行います。
初期化の失敗は、大抵の場合 ldstr.dll が見つからない事が原因です。初期化に失敗している時に繰り返し呼び出された場合、DLL の検索と失敗を繰り返す事になるので、全体の速度が低下する原因になります。
例.線を描画し、コンソールに座標情報を表示する
#include <windows.h>
#include "floatex.h"
VOID Draw_Line(
HDC hDC,
PFLOATEX px1,
PFLOATEX py1,
PFLOATEX px2,
PFLOATEX py2)
{
CHAR buf[32];
MoveToEx(hDC, floatex_tolong(px1), floatex_tolong(py1), NULL);
LineTo(hDC, floatex_tolong(px2), floatex_tolong(py2));
/*
Draw_Line の仕様として、座標の表示が無くても良い場合は、ldstr.dll を
置かなければ、線の描画だけを行います。しかし、ldstr.dll の初期化が毎
回行われるので、描画速度の低下を招きます。
*/
if (floatex_ldstr_ldtoa(px1, buf) >= 0){
printf("x1 : %s ", buf);
floatex_ldstr_ldtoa(py1, buf);
printf("y1 : %s ", buf);
floatex_ldstr_ldtoa(px2, buf);
printf("x2 : %s ", buf);
floatex_ldstr_ldtoa(py2, buf);
printf("y2 : %s\n", buf);
}
}
このケースの最も簡単な改善方法は、ldstr.dll を置き、初期化を成功させる事ですが、確実にしたい場合は、初期化処理を基幹側に行わせます。
VOID Draw_Line(
HDC hDC,
PFLOATEX px1,
PFLOATEX py1,
PFLOATEX px2,
PFLOATEX py2,
INT bInitSuccess) /* 0 ... 初期化に失敗している / 0 以外 ... 初期化に成功している */
{
CHAR buf[32];
MoveToEx(hDC, floatex_tolong(px1), floatex_tolong(py1), NULL);
LineTo(hDC, floatex_tolong(px2), floatex_tolong(py2));
if (bInitSuccess){
floatex_ldstr_ldtoa(px1, buf);
printf("x1 : %s ", buf);
floatex_ldstr_ldtoa(py1, buf);
printf("y1 : %s ", buf);
floatex_ldstr_ldtoa(px2, buf);
printf("x2 : %s ", buf);
floatex_ldstr_ldtoa(py2, buf);
printf("y2 : %s\n", buf);
}
}
(呼び出し側)
INT bInitSuccess;
/* メイン側の初期化処理 */
bInitSuccess = floatex_ldstr_init();
・
・
・
while(X ){
Draw_Line(hDC, x1, y1, x2, y2, bInitSuccess);
}
・
・
・
/* メイン側の終了処理 */
floatex_ldstr_term();
オブジェクト内での初期化
クラスのコンストラクタ内に floatex_ldstr_init を置く場合は注意が必要です。コンストラクタは、一つのオブジェクトで一度しか実行されませんが、クラスの用途によっては多量のオブジェクトを生成する場合があり、その時は個数分のコンストラクタが実行されます。つまり、floatex_ldstr_init が繰り返し実行されます。
テスト.
#include "floatex.h"
class CCnvFloatEX {
char private_buf[32];
public:
CCnvFloatEX()
{
floatex_ldstr_init();
private_buf[0] = 0;
}
~CCnvFloatEX()
{
floatex_ldstr_term();
}
char *operator=(PFLOATEX pval)
{
floatex_ldstr_ldtoa(pval,private_buf);
return private_buf;
};
char *out(void)
{
return private_buf;
};
};
#include <stdio.h>
// オブジェクトをローカルで使用する場合、関数自体が繰り返し実行されると、
// コンストラクタ、デストラクタも繰り返し実行される事になります。
void test(PFLOATEX pval)
{
CCnvFloatEX obj;
obj = pval;
printf("%s\n",obj.out());
}
int __cdecl main(void)
{
FLOATEX i,CMax;
unsigned oldcw;
oldcw = floatex_storecw();
floatex_loadcw(FEX_MCW_EM | FEX_PC_64 | FEX_RC_NEAR);
floatex_doubleto(10000.0,CMax);
for(floatex_setz(i);floatex_comp(i,CMax) <= 0;floatex_inc(i))
test(i);
floatex_loadcw(oldcw);
return 0;
}
ライブラリ化を考えないのであれば、Cの場合と同じように、基幹側に初期化/解放を行わせる事が理想的です。
一つのオブジェクトを末端の処理で使い回す構成にする事でも対処できます。
void test(CCnvFloatEX &obj,PFLOATEX pval)
{
obj = pval;
printf("%s\n",obj.out());
}
int __cdecl main(void)
{
FLOATEX i,CMax;
unsigned oldcw;
CCnvFloatEX obj; // 全体で一つだけならば、初期化/解放も一度だけ
oldcw = floatex_storecw();
floatex_loadcw(FEX_MCW_EM | FEX_PC_64 | FEX_RC_NEAR);
floatex_doubleto(10000.0,CMax);
for(floatex_setz(i);floatex_comp(i,CMax) <= 0;floatex_inc(i))
test(obj,i);
floatex_loadcw(oldcw);
return 0;
}