MT4/MQL4とWin32 API。

ここではMetaTrader 4で動くエキスパート・アドバイザーやスクリプトを記述するためのプログラミング言語、MQL4からWindowsの機能をWin32 API経由で呼び出す方法を、サンプルを交えながら解説します。

もっと短く言うと、kernel32.dllがエクスポートしている関数をMT4から呼び出して使おう!という趣旨の記事です。

1.MQL4の基礎知識

MQL4の公式ドキュメントにも記載がありますが、MT4にはDLLをロードしてその機能を利用するためのimportという機能があります。

例えばMQL4で1つ目のExpertSample.mqhのように書くと、それは2つ目のExpertSample.cで実装されているGetIntValue関数を、戻り値=int / 引数=intで呼び出せるようにExpertSample.dllをMT4にロードするという意味を持ちます。

/* ファイル名:ExpertSample.mqh */

#import "ExpertSample.dll"
int    GetIntValue(int);
#import
/* ファイル名:ExpertSample.c */

__declspec(dllexport) int GetIntValue(int value)
{
    return value;
}

2.Win32 APIの基礎知識

MicrosoftはWindowsで利用可能な各種APIのドキュメント、とりわけ関数の定義とその関数をエクスポートしているDLLに関する情報を公開しています。ここでは環境変数を取得するためのGetEnvironmentVariableAという関数を例に解説を進めます。

DWORD GetEnvironmentVariableA(
 LPCSTR lpName,
 LPSTR  lpBuffer,
 DWORD  nSize
);

まず知るべきことは、関数の最後につく文字の意味です。AはANSI、WはWideを意味し、語弊を恐れずに言い切ると、Aは半角英数字用、Wは全角日本語用を表していると思って差し支えありません。

次にページの下部にはその関数をエクスポートしているDLLと、サポートされるWindowsの情報が記載されています。

画像1

3.MQL4とWin32 APIの型翻訳

ここからがキモです。Win32 APIで型として出てきたDWORDやLPCSTR、LPSTRは、MQL4に存在しません。存在しませんが、型は必ず合わせないといけないので、Win32 APIの型をMQL4の型に翻訳する必要がでてきます。

↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓

ひとつずつ詳しく見ていくと、

・DWORDは32ビット符号なし整数、なのでuint
・LPCSTRとLPSTR はNULL終端の8ビット文字列へのポインタ、なのでuchar配列の参照渡しと同義

という方針が立ちます。そしてここまでの内容をコードにするとkernel32.mqhのようになり、これで一応はMQL4からWin32 APIのGetEnvironmentVariableA関数を呼び出す準備が整いました。

/* ファイル名:kernel32.mqh */

#import "kernel32.dll"
uint GetEnvironmentVariableA(
 uchar& lpName[],
 uchar& lpBuffer[],
 uint nSize
);
#import

4.Wrapper関数の作成

しかしこのGetEnvironmentVariableAという関数、文字列がMQL4で通常使われるstringではないので、このままでは非常に使いづらい代物です。よって使い勝手を向上させるためのWrapper関数を最後に作成します。

まずMQL4での文字列の型変換には、これらStringToCharArrayとCharArrayToStringを使用します。

そして環境変数の最大文字数についてはMicrosoftのドキュメントで言及されている32,767文字を、さらにGetEnvironmentVariableAが戻り値0(エラー)を返した場合には明示的に空文字を返すようにコードを書くと、以下のようになりました。

/* ファイル名:kernel32.mqh (さっきの続き) */

string GetEnvironmentVariable(string name) {
   uchar lpName[];
   uchar lpBuffer[32767];
   uint nSize = 32767;

   StringToCharArray(name, lpName);
   if ((nSize=GetEnvironmentVariableA(lpName, lpBuffer, nSize)) != 0) {
       return CharArrayToString(lpBuffer, 0, nSize);
   } else {
       return "";
   }
}

これでようやく使い勝手の良いGetEnvironmentVariable関数が完成です。expert.mq4のように直感的に使えます。

/* ファイル名:expert.mq4 */

#include <kernel32.mqh>

int OnInit() {
   PrintFormat("USERNAME=%s",
               GetEnvironmentVariable("USERNAME"));

   return INIT_SUCCEEDED;
}

実行時には、DLLの使用を許可してください。

画像2

5.あとがき

ここに書いたセオリーを理解し、そしてそのキモとなる型の翻訳をマスターすれば、MT4のエキスパート・アドバイザーやスクリプトを自在に拡張できるようになります。

これが何を意味するかわかりますか?そう、Pythonでもクラウドでも何でも、アナタのとっておきをMT4の世界に持ち込むドアが開かれるということです。

ご健勝をお祈りします。

Let's きっちり納税。noteでの収益を励みに、皆さんへ有益な情報を届けます!