DLLでグローバル変数の確保方法

このQ&Aのポイント
  • Visual c++ 2008 express editionを使い、mt4(為替取引用標準的トレードツール)用のDLLを作成する方法について教えてください。
  • 作成したDLLのプログラムはvc2008と初めて使うので、よく見えない部分があります。サンプルプログラムを参考にして、ファイルへの書き込みやクローズ処理を試しています。
  • DLLなので、MT4プログラムと一緒にコンパイルリンクはできません。そのため、処理に必要なメモリ領域の確保方法がわかりません。グローバル変数で確保する方法を教えて欲しいです。
回答を見る
  • ベストアンサー

DLLでグローバル変数の確保方法

Visual c++ 2008 express edition を使い、mt4(為替取引用標準的トレードツール)用のDLLを作ろうとしています。 DLLのプログラムもvc2008も初めて(普段はBCB6でwindowアプリに使っている)なのでよく見えないところがあります。 サンプルプログラムを参考に、func_openで書き込みファイルをopenし、そのあとイベントが発生するたびに、func_putが呼ばれ、ファイルに蓄積し、何日か連続して運転後、func_closeが呼ばれ、ファイルをクローズする処理を下記サンプルとして試しています。 よく見えないことは、DLLなので、MT4プログラムと一緒にコンパイルリンクをすることはできませんので(当然ですが)、処理に必要な多くのメモリ領域を、運転中保持しておく方法が、見えないことの眼目です。 この例の場合は、ファイルポインターfpwを保持しておくために、第1行目のstatic宣言をしました。とりあえずfunc_putを1回呼ぶだけの処理を試したところ、正しくファイルには書き込まれていました。 他にmalloc関数などを使う方法もあろうかと思いますが、本例のようにグローバル変数で確保、保持できれば、見通しがよくなりますので、問題なければこの方法を採用したいのです。 他の条件として、このDLL関数群は、異なるMT4あるいは、MT4内の複数のプロセス(?)から呼ばれることはありません。  そこで、お聞きしたいことは、static宣言で、メモリーリーク(開放されずに残る)や、意図しないstaticでない状態(内容が破壊される)などの問題がでないでしょうかということです。ようするに正しい使い方でしょうかがよくわからないのです。 サンプルコード static FILE *fpw; // この記述で不都合がないか? BOOL APIENTRY DllMain(HANDLE hModule, DWORD........) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH; ....... return(TRUE); } MT4_EXPFUNC int __stdcall func_open(const int ipar) { fpw=fopen("c:\\fx\\log.txt","w"); return(1); } MT4_EXPFUNC int __stdcall func_put(const int val) { fprintf(fpw,"static=%d",val); // その他いろんな処理 return(0); } MT4_EXPFUNC int __stdcall func_close(void) { fclose(fpw); return(0); }

質問者が選んだベストアンサー

  • ベストアンサー
  • tanteiq
  • ベストアンサー率20% (1/5)
回答No.1

C++ならクラスを使ってはどうですか? それとファイルポインタもポインタの受け渡しの方がいいですよ ちなみにグローバル変数はたしかstaticです(プログラムが終わる時に破棄される) staticで自動的に破棄されるのは上のコードで言うファイルポインタなのでそのデータ自体はきちんと閉めないと普通にメモリリークします >>意図しないstaticでない状態(内容が破壊される) こちらはちょっと質問の意図が分かりません

qhtsige
質問者

お礼

ご返事ありがとうございます。 static宣言のメモリはプログラムが終了(強制終了?も)すると、自動的に開放されるのですね。確保操作を特にしないので当然ですか。それに対して*fpwのファイルポインタはfcloseしてやらないと、残ってしまうのですね。なるほどです。 特にDLLといって特別な概念はなさそうに思いました。 それからiostreamクラスのことですね。長年入出力はランタイムライブラリを使っているので、便利そうな機能もあるようですが、なかなか踏み切れません。C++といっても、代替機能が無い場合に使うだけです。

関連するQ&A

  • EXE1→DLL→EXE2数値を受け渡す方法

    C++プログラムの初級者です。 EXE1の数値をDLLの関数Func1に渡し、そこで計算した結果を関数Func2でEXE2に送るプログラムを作成しています。 下記のようなDLLのコードを作成したのですが、うまく数値を受け渡すことが出来ません。 調べてみると、EXE1⇔DLLとEXE2⇔DLLとは、アドレス空間が別なので、DLLのStatic変数を共有できないようです。 EXE1⇔DLL と EXE2⇔DLL の1対1では数値受け渡しは、正常に動作しています。 具体的に、DLLにどのようなコードを書けば、数値を受け渡すことができるのでしょうか? ご指導よろしくお願いします。 VC++2010ExpressEdition で作成しています。 <DLLのソースコード> ---------------------- #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdlib.h> #include <stdio.h> #include <iostream> static double aa, bb; __declspec(dllexport) double __stdcall Func1(double a1, double b1) { aa = a1*2; return (double)(aa); } __declspec(dllexport) double __stdcall Func2(double a2, double b2) { return (double)(aa); } BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) { //---- switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } //---- return(TRUE); }

  • static変数の扱いについて

    例えば、下記のような場合、 main(){ ・・・ while(A==B){ kakunin1();//この関数を何度か繰り返し呼び出す } } int kakunin1(){ static int sample = 0.0; kakunin2(&sample); sample++; //(1) return(sample); } void kakunin2(*sample){ *sample++; //(2) } まずはじめに(2)でsample=1になって、 次に(1)で2になって、 今度mainからkakunin1がコールされると、sampleの値は2を 保持しているのでしょうか?つまりその後(2)でさらにsample=3と なるのでしょうか?

  • static 変数について

    static 変数について 今、C++を勉強しているのですか、static変数がどのように動くのかよくわかりません。 下のプログラムのint a はローカル変数だから、ブロックを抜けたら、初期化されるためstatic変数にして、ブロックを抜けても値を保持するようにすってことはわかるのですが 毎回このブロックに入る度、static int a = 0;を読むことになり、その前に入っていた値はなくなるのではないでしょうか?それとも,static int a と書かれていると,1度しか実行されないから、値が保持され続けるのでしょうか? int add (int x ) { int a = 0; a += x; return a; }

  • 実行時dllを動かしたい

    のですがサイトで見つけたdllの作り方を見て 大人気の無償Borland C++5.51を使って //mydll.cpp #include <windows.h> BOOL __stdcall MyBeep() { return MessageBeep(0); } int __stdcall MyMessageBox(LPCTSTR lpszMessage) { return MessageBox(NULL,lpszMessage,"",0); } を bcc32 -WD mydll してmydll.dllを作り //myexe.cpp #include <windows.h> typedef int (__stdcall *pMyFunction)(LPCTSTR); int APIENTRY WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { HINSTANCE hLib; pMyFunction pMyMessageBox; hLib = LoadLibrary("mydll.dll"); if(hLib) { pMyMessageBox=(pMyFunction)GetProcAddress(hLib,"MyMessageBox"); if(pMyMessageBox)(*pMyMessageBox)("HELLO!!"); FreeLibrary(hLib); } return 0; } を bcc32 -W myexe してmyexe.exeを作り myexe.exe したのですがHELLO!!がでません。 どうしたらいいのでしょうか?

  • クラス内の関数内static変数について

    クラス内の「staticではないメンバ関数内で定義される」static変数の初期化タイミングはいつでしょうか? 自分としてはクラスのインスタンス生成時に初期化されるものだと思っていたのですが、どうもそうでは無さそうだという現象に出会ったもので。 例えば以下のようなサンプルプログラムがあるとします。 --------------------------------------- class TA { public: void func(int i); }; void TA::func(int i) { static int d=0; d += i; std::cout << d << std::endl; } int main() { for(int i=1; i < 3;i++) { TA ta; ta.func(i); ta.func(i); ta.func(i); } } --------------------------------------- これを実行した時、自分としては 1 2 3 2 4 6 という結果を期待していた訳ですが、実際には 1 2 3 5 7 9 という結果になりました。 ということは、もしかしてメンバ変数ではなくともクラス内に現れるstatic変数はstaticなメンバ変数と同等ということなのでしょうか? 実際、上記ソースのforループ内にもう一つclass TAのインスタンスtbを追加してみると、 --------------------------------------- for(int i=1; i < 3;i++) { TA ta; ta.func(i); ta.func(i); ta.func(i); TA tb; tb.func(i); tb.func(i); tb.func(i); } --------------------------------------- 1 2 3 4 5 6 8 10 12 14 16 18 となりました。 (まぁstaticではないメンバ変数に置き換えれば一応解決するのですが、個人的に何か凄く気持ち悪く感じて・・・)

  • C#でWin32 MFC DLLが呼び出せない

    C#で以下のエラーが発生し、非常に困ってます。 色々とサイトを見たのですが、DLLが本当にないのでは?という意見が多かったです。 しかし、私の方はDLLファイルはbin->debugフォルダ , obj->debugフォルダ、System32に置いてます。 問題が分かる方、是非教えてください! using System.Runtime.InteropServices; namespace WindowsFormsApplication { public partial class Form1 : Form { [DllImport("Win32DLL_TEST.dll")] private extern static int func(int x, int y); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int n = func3(5, 7);//ここでエラー! } } } エラー内容 'System.DllNotFoundException' のハンドルされていない例外が WindowsFormsApplication.exe で発生しました。 追加情報: DLL 'Win32DLL_TEST.dll' を読み込めません: 指定されたモジュールが見つかりません。 (HRESULT からの例外: 0x8007007E) 備考 DLLは自作のWin32 DLL です。 extern "C"{ __declspec(dllexport) int __cdecl func(int x, int y) } と宣言し、VC++のMFC dialog上では呼び出しを成功しています。

  • DLLをGetProcAddress()で実行できない。

    dllの操作の練習をしております。以下のソースのどこがおかしいのでしょうか? add.dllの内容は単にa+bの結果をメッセージボックスに表示させるだけの処理です。add.lib(インポートライブラリ)をリンクさせればうまく動きます。 しかし、GetProcAddress()を使って明示的にdllを呼び出そうとすると、コンパイルエラーで ADD(hWnd,5,5); の行に 「int (__stdcall *)(void)' : 実引数が多すぎます。」 となります。このメッセージの意味もわかりません。 以下のソースのどこがおかしいのでしょうか?コンパイラはVC++6.0でOSはWin2000です。 #include<windows.h> void CALLBACK ADD(HWND hwnd,int a, int b); //ウィンドウプロージャ(ここは別に普通) LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow) { static FARPROC ADD;  //あやしい HWND hWnd; MSG msg; WNDCLASS winc;     //ウィンドウを作る処理 //~(省略)~ /****明示的にdllを呼び出す****/ ADD = GetProcAddress( LoadLibrary(TEXT("add.dll")) , TEXT("ADD")); ADD(hWnd,5,5); /****************************/ while (GetMessage(&msg , NULL , 0 , 0 )) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } お願いします。

  • perlでWin32::APIを使用してDLLからバイナリデータを得たいのですが、

    perlでWin32::APIを使用してDLLからバイナリデータを得たいのですが、 データ途中できれてしまいます。 0x00を含むところで切れているように思えます。 $datの長さを指定する方法とかあるのでしょうか? どうか助言をお願いします。 $func=new Win32::API("sample.dll","func1",[P,N,P],P); $size=0; $dat = $func ->Call("TEST",100,\$size); open(F,">kekka"); binmode(F); print F "$dat"; close(F);

    • ベストアンサー
    • Perl
  • 変数の値がおかしくなる

    以下のようなプログラム(DLLとEXE)を書いたのですが、変数の値がおかしくなる(●参照)箇所があります。原因がお分かりになりましたら、ご回答をよろしくお願い致します。 ●mkdll.cppの、sub1()の(※1)までは、input[]が正しい値で入っているが、(※2)で値がおかしくなる。(※1)から(※2)までで、input[]は参照するだけです。 ---test.cpp(EXE)--- … main(){ int input[10],output[10]; int err; CDLL DLL; err = DLL.func(input,output); … return(0); } ---test.cpp End--- ---mkdll.h(DLL)--- … class __declspec(dllexport) CDLL{ public: int func(int *input, int *output); private: int sub1(int *input, int *output); int sub2(int in, int out); … }; ---mkdll.h End--- ---mkdll.cpp(DLL)--- #include "mkdll.h" … int CDLL::func(int *input, int*output){ int i; int error; error = sub1(input, output); return(error); } int CDLL::sub1(int *input, int *outout){ int i; int in1, in2, out1, out2; int err; //(※1) for(i=0; i<5; i++){ err = 0; in1 = input[i*2]; in2 = input[i*2+1]; //(※2) err = sub2(in1, out1); if(err != 0) return(err); … } } … ---mkdll.cpp End---

  • ダイアログベースアプリのDLL化の方法について

    ダイアログベースで作成してあるアプリexeを DLL化するのですが、その方法が分かりません。 ダイアログの使用はやめるつもりです。 これまでやってみたことは、 プロジェクトのプロパティで、EXEファイルからDLLに設定を 変更しました。 http://hp.vector.co.jp/authors/VA019517/howtodll.html サンプルを見て、既存のソースに__stdcallなどを記載したいのですが DLLが作成されませんでした。 新規にプロジェクトを作成して、サンプル通りにやった場合は DLLが作成されました。 呼び出したい関数は、別々のファイルですが、 1つのファイルにまとめる必要がありますか? ダイアログベースはやめます。 この2つの関数は、同じDLLにします。 ↓DLL化するソース。ここを外部EXEから呼び出したい。 Test_aa_App.cpp --------------------------------------- CTest_aa_App::InitInctance(){ //初期化処理 } ↓呼び出し対象DLL Test_bb_Dlg.cpp -------------------------------- CTest_bb_Dlg::Test() { // 処理 } 初歩的なことだと思いますが、まず、どのように ソースを変更すれば良いか教えてください。 VS2003 C++6.0 よろしくお願いします。

専門家に質問してみよう