Visual C++ 2010 ExpressでDLLを作成する 〜 DLLをMetatrader4(MT4)で使用する
今回のエントリーを残すことになった背景は「【未解決】作成したDLLをMT4で動かしたいが、動かない」。
Linuxでmingwを使用して作成したDLLを、windows8で動作させているMT4プログラムでimportして動かしたかったが動かなかった問題。
windows7で動いていたので不思議だったが、ひょっとして同じOS(windows上)でDLLを作成しないといけないのかと(根拠の無い)仮定を置いたのが動機・背景。
Visual C++ 2010 Expressを起動する。
1.新規プロジェクトの作成
2.DLLソースコードの作成
3.DLLプロジェクトのビルド
4.DLL呼び出しソースコードの作成
5.DLL呼び出しソースコードの実行
1.新規プロジェクトの作成
メニューの「ファイル」→「新規作成」→「プロジェクト」を選択する。
「新しいプロジェクト」のウィザードが表示されるので「Win32プロジェクト」を選択する。
Win32アプリケーションウィザードが表示されるので、左側の「アプリケーションの設定」を選択する。
「アプリケーションの種類」に「DLL」を、「追加のオプション」に「空のプロジェクト」を選択する。
プロジェクトの作成完了
2.DLLソースコードの作成
まず、DLL外部*1から呼び出すDLL関数(エクスポート関数)には、__declspec(dllexport)という修飾子をつける。
※)毎回書くのは面倒なので#defineでマクロを用意しておくと良いかも。
#define EXPORT __declspec(dllexport) EXPORT double movingAverages(double a, double b, double c, double d);
これが基本だが、これだとC++の規則に則ったDLLが作成される。それだと、DLLを呼び出すプログラムがCでビルドされたものだと上手く行かない。
なぜなら、リンカがプログラムの関数名をそのまま使用するのではなく、修飾された関数名を使用するから。
そこで、修飾名をC++のものからCのものへ変更する必要がある。そのために、エクスポート関数に「extern "C"」という修飾子を追加する。
さらに、「extern "C"」はC++でのみ有効なものなので、C++でビルドする場合だけ付けるように#ifdefで条件分岐したソースコードとする。
#ifdef __cplusplus #define EXPORT extern "C" __declspec(dllexport) #else #define EXPORT __declspec(dllexport) #endif EXPORT double movingAverages(double a, double b, double c, double d);
こうして作成したのが次のソースコード(test.cpp)
#include <Windows.h> #ifdef __cplusplus #define EXPORT extern "C" __declspec(dllexport) #else #define EXPORT __declspec(dllexport) #endif EXPORT double movingAverages(double a, double b, double c, double d); BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ){ return TRUE; } EXPORT double movingAverages(double a, double b, double c, double d) { return((a+b+c+d)/4); }
※)ifdefの部分とEXPORTの部分を毎回書くのは面倒なので、次のようにヘッダファイルを作成してそこに書いておいてもいい。ただし、今回は余計なファイルを増やしたくなかったので、ヘッダファイルは使用していない。MT4に配置するときに持っていくものが増えるのも嫌だし。
#include <Windows.h> #include "testdll.h" BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ){ return TRUE; } EXPORT double movingAverages(double a, double b, double c, double d) { return((a+b+c+d)/4); }
3.DLLプロジェクトのビルド
プロジェクトを右クリックしてビルドする。
ビルドしたらtestdll.dllとtestdll.libが作成される。
ただ、これがvisual C++ Expressのソリューションエクスプローラーから見えない。仕方がないのでプロジェクトフォルダ(\visualStudio2010Projects\testdll\Debug)を確認する。
4.DLL呼び出しソースコードの作成
Visual C++(以下、VC++)のアプリケーションを作成したいのなら、作成したDLLを呼び出すソースコードをVC++で作成すればよいのだろう。
ただ、今回はMT4でDLLを使用することが目的なので、DLLを呼び出すソースコードはMQL4で作成する。
作成したソースが次のもの。ファイル名は「dllTest2.mq4」。実はこれ、「【未解決】作成したDLLをMT4で動かしたいが、動かない」で作成したものと殆ど同じで、違うのはimportするDLL名。今回は「testdll.dll」を作成したので、その名前を指定している。
//+------------------------------------------------------------------+ //| dllTest2.mq4 | //| Copyright 2014, graySpace | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, graySpace" #property link "http://www.mql5.com" #property version "1.00" #property strict #import "testdll.dll" double movingAverages(double,double,double,double); #import //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- double testNum = movingAverages(1,2,3,4); Print("***************",testNum); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
5.DLL呼び出しソースコードの実行
MT4のソースを作成したらバックテストとして動かす。
実行環境は次の通り。
OSの種類 | MT4提供会社 | MT4のバージョン | MT4のbuild番号 |
Windows8.1 64bit | Metaquotes | 4.00 | 711 |
これで「【未解決】作成したDLLをMT4で動かしたいが、動かない」で記載した問題が解決した。