私にとって大きな壁に突き当たり1ヶ月が過ぎてしまいました、どなたか助けて頂けませんでしょうか。
ベストなズバリサンプルコードを頂いた方に追加で2000P差し上げたいと思います。
Mail : metatrader4.0\gmail.com (\=@)
※はてな会員以外の方でサンプルコードを頂ける場合は、paypal か 銀行振り込みで 2000P = 2000円を差し上げます。
ご連絡下さい。
質問文字数制限のためコメント欄に【本題】を記入いたします。
サンプルコードではありませんが、クラッシュする原因はたぶん以下のとおりだと思います。
V. Testing the DLLs in MetaTrader 4 にも書いてありますが、
CSharpAssembly.dll と CppStdcallInerfaceWrapper.dll を experts\libraries に置いていませんか?
CSharpAssembly.dll は Terminal.exe -> CppStdcallInerfaceWrapper.dll -> CSharpAssembly.dll
と呼び出されますが、Terminal.exe は CSharpAssembly.dll を見つけることができないため
クラッシュしています。
dll を MetaTrader のインストールディレクトリ(Terminal.exe と同じ場所)に置くと動くと思います。
ちなみに、CLR は以下の順で DLL を検索します (CLR は環境変数 PATH を利用しません)。
http://codezine.jp/article/detail/2236
あと、Explanations about the Step-by-Step Guide に書いてあることは要約すると以下のようになります。
トレーディングプラットフォーム Metatrader4(※1) と言うアプリケーションは、様々な市場に対して、搭載しているMQL言語(※2)(ポインタのないCによく似たコンパイラ)を使い独自の取引ルールをシステム化して、自動取引を行えるアプリケーションです。
この Metatrader4 MQL には外部DLLを呼び出す #import ディレクティブがあり、Windows API 等を呼び出すことが出来る仕様になっており、簡単に API を呼び出せます。
例)
#import "user32.dll"
int MessageBoxA(int hWnd ,string szText, string szCaption, int nType);
start() {
‥ MessageBoxA(100, "テストメッセージ" , "", 0);
}
この #import 文を使い C#のDLLを C++/CLIでラップしてコールしたいのです。
MQL #import --> C++/CLIのラッパーDLL --> C#DLL
まず Metatrader4(※1) に付属している MQLからDLLをコールするサンプル(※3)を VS2008に読み込みテストしたらうまくコールできていましたので、自分でも簡単なテストコードを書いて実行しても正常に、引数、戻り値付きでコールできることは確認しております。
MQL #import --> C++/CLI DLL
【サンプルDLL確認方法】参照。
次に目的の C#DLL をコールする方法ですが、サイトを彷徨っているとこんな(※4)サイトがあったので早速チャレンジしました(英語は全く読めません(^^;)
解説されてる方法をVS2005用のソリューションファイル [DotNetDllForMetaTrader4_demo.zip] として下の方にあったので実行してみましたが Metatrader4 がクラッシュしてしまいます。
ここからプログラミングの深い樹海へ迷い込んでしまいました。
今までやったことは
[DotNetDllForMetaTrader4_demo.zip]がおかしいと思いサイトの手順通りやったがダメ。
DLLの仕組みを調べ __declspec(dllexport) や export "C" , __stdcall(その他の呼び出し規約も) , モジュール定義ファイル(.def) この辺をいじくってもダメ。(当然正しくいじくってはいない可能性大)
試行錯誤をしてる中でどうも C++/CLI DLL --> C#DLL 呼び出しコードを記述すると Metatrader4 がクラッシュすることに気付いた。
調べるために、C#,C++,C の実行ファイルから DLLをコール
C#.exe --> C++/CLI DLL Func1():unmanaged --> C++/CLI DLL Func2():C#DLLをcall
C++.exe --> C++/CLI DLL Func1():unmanaged --> C++/CLI DLL Func2():C#DLLをcall
C.exe --> C++/CLI DLL Func1():unmanaged --> C++/CLI DLL Func2():C#DLLをcall
は正常にコールできた。
次に
MQL #import --> C++/CLI DLL Func1():unmanaged --> C++/CLI DLL Func3():C#DLLをcall
MQL #import --> C++/CLI DLL Func1():unmanaged --> C++/CLI DLL Func2():managed APIをcall --> C++/CLI DLL Func3():C#DLLをcall
Func1(), Func2() までは正常にコールできたが、どうしても、Func3()をコールした時点でクラッシュしてしまう。
MQL #import --> C++/CLI DLL Func1() が呼び出せていると言う事は呼び出し規約は__stdcallで間違いない。
Func2()にも制御が移っているので、C++/CLI内のコードには問題ない。
Func3()だけなぜコールできないのだろう?
(※4)サイトの下の方に Explanations about the Step-by-Step Guide 3行目に気になる表現が…でも意味が分からん(-_-)
もしかして、ネイティブとマネージドのメモリ管理の違いかなと勝手に解釈して再び樹海へ…
:
:
もう能力の限界と思いこちらへ来ました (- -)
お願いは、MQL #import --> C++/CLIのラッパーDLL --> C#DLL が実行できる Visual Studio 2008(2005) 用のソリューション サンプルコード ファイルをメールで頂けませんでしょうか。
サンプルコードには、MQL側から見て
string DllFunc(string);
int DllFunc(int);
double DllFunc(double);
bool DllFunc(bool);
string[] DllFunc(string[]);
string[,] DllFunc(string[,]);
int[] DllFunc(int[]);
int[,] DllFunc(int[,]);
double[] DllFunc(double[]);
double[,] DllFunc(double[,]);
の各呼び出しサンプルを肝の部分のコメント付きで記述して頂けたらと思います。(その他サンプル追加は大歓迎)
【サンプルDLL確認方法】
(付属のサンプルDLLをコールしてみる)
1、 Metatrader4(※1) をインストールする。
2、 デモアカウント取得のダイアログが出てくるので適当な情報を書き込み取得する。
3、 C:\Program Trade Tool\MT4\Alpari_Demo\experts\samples\libraries\ExpertSample.dll ファイルを
‥‥ C:\Program Trade Tool\MT4\Alpari_Demo\experts\libraries\ フォルダにコピーする。
4、 C:\Program Trade Tool\MT4\Alpari_Demo\experts\samples\include\sampledll.mqh ファイルを
‥‥ C:\Program Trade Tool\MT4\Alpari_Demo\experts\include\ フォルダにコピーする。(DLLインポート用ヘッダ)
5、 C:\Program Trade Tool\MT4\Alpari_Demo\experts\samples\ExportFunctions.mq4 ファイルを
‥‥ C:\Program Trade Tool\MT4\Alpari_Demo\experts\ フォルダにコピーする。(メインコード)
6、 Metatrader4 を起動する。
7、 メニューの[ツール] - [MetaQuotes Language Editer] をクリックして MetaEditer を起動する。
8、 右ペインに "ExportFunctions.mq4" が表示されてるのでダブルクリックでファイルをオープンする。
9、 メニュー下のツールボックスのアイコンから [Compile] をクリックして正常にコンパイルされたか確認して
‥‥ (下ペインに 0 error(s), 0 warning(s) が表示されればOk)MetaEditerをクローズする。
10、 Metatrader4 の下ペインの [Experts] タブを選択する。
‥‥ (ここにメインコードに記述してある Print文 のメッセージが表示される)
11、 Metatrader4 の左ペイン下段にある [Expert Advisors]フォルダ(青い帽子をかぶった専門相談員!?)を
‥‥ 展開したら "ExportFunctions" が表示されてるのでドラッグして右にあるチャートのどれでも良いので
‥‥ ドロップする。
12、 ダイアログが表示されるので [OK] ボタンを押すと、下ペインExpertタブに、
‥‥ メインコードに記述してある Print文 のメッセージが表示される。
(付属のVC++用サンプルをコンパイルして確認してみる)
1、 C:\Program Trade Tool\MT4\Alpari_Demo\experts\samples\MT4DLLSample\
2、 フォルダにに有るVC++プロジェクトをVSに読み込む。
3、 コンパイルする。
4、 生成されたDLLを …\libraries\ フォルダにコピーする。
5、 後は、(付属のサンプルDLLをコールしてみる)10、からの手順と同じ
(※1) MetaTrader 4 Client Terminal ダウンロードサイト
‥‥ http://www.metaquotes.net/downloads/
‥‥ ※Vista では C:\Program files\ フォルダにインストールするとトラブル可能性があるので違うフォルダが良い.
(※2) MetaTrader 4 Client Terminal MQL言語リファレンス
‥‥ http://docs.mql4.com/
(※3) MetaTrader 4 Client Terminal インストール後の DLL サンプルフォルダ
‥‥ C:\Metatrader Install Folder\experts\samples\
(※4) metatrader4 から C# DLL 呼び出しサンプルサイト
‥‥ Exporting .NET DLLs with Visual Studio 2005 to be Consumed by Native Applications
‥‥ http://www.codeguru.com/csharp/.net/cpp_managed/windowsservices/print.php/c14735
【環境】
Vista(メイン)、XP もあります。
Visual Studio 2008
スキル:早く初心者から抜け出したい…
C:\Program Trade Tool\MT4\Alpari_Demo\ ==> C:\metatrader インストールフォルダ\
http://q.hatena.ne.jp/1243530420
ネイティブであるMT4(metatrader)から直接マネージドであるC#DLLをコールするのは大変難しそうなのでC++/CLIのラッパーを経由してコールしたいと思っています。
Exporting .NET DLLs with Visual Studio 2005 to be Consumed by Native Applications
http://www.codeguru.com/csharp/.net/cpp_managed/windowsservices/print.php/c14735
の下の方にこんな文があり気になっています。
意味が分かる方教えて頂けませんでしょうか。
Another way of passing data to the unmanaged MetaTrader is not by creating an unmanaged copy, but by using the System.InteropeServices.GCHandle to pin the needed managed object while using it in the unmanaged MetaTrader, so the Garbage Collector doesn't move or delete it.
Other thing you sould take care of is the ecoding convention. .NET strings are in Unicode, whereas the calling application can support only ASCII, like with MetaTrader.
クラッシュというのはこれが原因の可能性が高いですね。
で、英語の部分ですが、ネイティブから参照したいメモリはSystem.InteropServices.GCHandleを使ってGC対象にならないように固定(pin)しておく必要がある、ということです。
ありがとうございました。