Visual C++ 2010 ExpressでDLLを作成する 〜 DLLをMetatrader4(MT4)で使用する

今回のエントリーを残すことになった背景は「【未解決】作成したDLLをMT4で動かしたいが、動かない」。
Linuxmingwを使用して作成した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で動かしたいが、動かない」で記載した問題が解決した。

*1:例えばC言語で書いた別のプログラムやMT4のプログラム