表題の通りですが、インターネットを渉猟してもあまり成果がなかったので、備忘録として残しておきます。
背景
MQL4 から DLL による共有メモリを利用したい。(他プロセスと通信する時に便利なので。)
お金を出せば売っているが、参入障壁が低い技術に4000円も払いたくない。
一方、MS の VC++ のコミュニティ版は古いし、製品版はバカ高くて手が出ない。
そこで、手軽な mingw を使えないか、画策してみることにした。
コード
いきなりですが、作成した DLL のコードを載せておきます。
#include <windows.h>
class SharedMemory {
private:
DWORD MemorySize = 1000 * 3 * sizeof(LONG);
HANDLE handle = NULL;
LPVOID lpPointer = NULL;
public:
SharedMemory(const char *name) {
open(name);
}
~SharedMemory() {
close();
}
void write(int type, long tag, long value) {
LONG *lpCell = (LONG *)lpPointer;
lpCell[type * 3 + tag] = value;
}
long read(int type, long tag) {
LONG *lpCell = (LONG *)lpPointer;
return lpCell[type * 3 + tag];
}
private:
void open(const char *name) {
close();
handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MemorySize, name);
if (handle == NULL) {
return;
}
lpPointer = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpPointer == NULL) {
CloseHandle(handle);
return;
}
ZeroMemory(lpPointer, MemorySize);
}
void close() {
if (lpPointer != NULL) {
UnmapViewOfFile(lpPointer);
}
if (handle != NULL) {
CloseHandle(handle);
}
}
}
};
static SharedMemory mem("mql4_shared");
extern "C" __declspec(dllexport) void write_a(long tag, long value) {
mem.write(0, tag, value);
}
extern "C" __declspec(dllexport) long read_a(long tag) {
return mem.read(0, tag);
}
extern "C" __declspec(dllexport) void write_b(long tag, long value) {
mem.write(1, tag, value);
}
extern "C" __declspec(dllexport) long read_b(long tag) {
return mem.read(1, tag);
}
extern "C" __declspec(dllexport) void write_reg(long tag, long value) {
mem.write(2, tag, value);
}
extern "C" __declspec(dllexport) long read_reg(long tag) {
return mem.read(2, tag);
}
Windows の名前付き共有メモリを使っています。リソースの取得と解放が自動で行えるので、言語は C++ を使用しました。(エラートラップ全然入れていませんが、個人利用なので大目に見ることにします。)
ミソは export する関数を定義する際、__stdcall を入れないことです。
これを mingw g++ コンパイラでコンパイルして dll を作成し、
g++ -o common.dll -shared common.cc
MQL4 のデータフォルダの Terminal > (ハッシュ文字列) > MQL4 > Libraries の下にコピーします。
libstdc++-6.dll, libgcc_s_dw2-1.dll にも依存しているので一緒にコピーします。
(mingw インストールフォルダの、mingw/bin の下にあります。)
あとは MQL4 のスクリプトで、
#import "libgcc_s_dw2-1.dll"
#import "libstdc++-6.dll"
#import "common.dll"
void write_a(int, int);
int read_a(int);
void write_b(int, int);
int read_b(int);
void write_reg(int, int);
int read_reg(int);
#import
と定義すれば write_a(), ... 等の関数が利用できるようになります。