首先,我要说我对DLL不太了解。
我试图使用来自kernel32.dll
的函数将数据从一个程序发送到另一个程序。我的程序是用MQL4编码的。
这是我为服务器部分使用的代码,它应该保存数据:
#define INVALID_HANDLE_VALUE -1
#define BUF_SIZE 256
#define PAGE_READWRITE 0x0004
#define FILE_MAP_ALL_ACCESS 0xf001F
#import "kernel32.dll"
int CreateFileMappingA(int hFile, int lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
int MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
int UnmapViewOfFile(int lpBaseAddress);
int RtlMoveMemory(int DestPtr, string s, int Length);
int CloseHandle(int hwnd);
int CreateMutexA(int attr, int owner, string mutexName);
int ReleaseMutex(int hnd);
int WaitForSingleObject(int hnd, int dwMilliseconds);
bool started = False;
int hMapFile = 0;
int pBuf=0;
int hMutex;
int OnInit()
{
if(!started) {
started = true;
string szName="Global\\Value1";
int hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,BUF_SIZE,szName);
if(hMapFile==0) {
Alert("CreateFileMapping failed!");
return;
}
pBuf = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
if(pBuf==0) {
Alert("Map View failed!");
return;
}
hMutex = CreateMutexA(0,0,"PriceMapMutex");
}
}
void OnTick()
{
WaitForSingleObject(hMutex,1000);
if(pBuf==0) return;
string szMsg = DoubleToStr(Bid,Digits);
Comment("Data: ",szMsg);
RtlMoveMemory(pBuf, szMsg, StringLen(szMsg)+1);
ReleaseMutex(hMutex);
return(0);
}
int deinit()
{
switch(UninitializeReason()) {
case REASON_CHARTCLOSE:
case REASON_REMOVE:
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
break;
}
return(0);
}
这就是我为我的客户端所使用的,它应该用来获取数据:
#define INVALID_HANDLE_VALUE -1
#define BUF_SIZE 1024
#define FILE_MAP_READ 4
extern int BufferSize = 1024;
#import "kernel32.dll"
int OpenFileMappingA(int dwDesiredAccess, bool bInheritHandle, string lpName);
string MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
int UnmapViewOfFile(string lpBaseAddress);
int CloseHandle(int hwnd);
int CreateMutexA(int attr, int owner, string mutexName);
int ReleaseMutex(int hnd);
int WaitForSingleObject(int hnd, int dwMilliseconds);
string szName;
int hMapFile;
string obj;
string data;
int hMutex;
double dd;
int OnInit()
{
szName="Global\\Value1";
hMapFile = OpenFileMappingA(FILE_MAP_READ,False,szName);
if(hMapFile==0) {
Alert("CreateFile Failed!");
return;
}
obj="data";
ObjectCreate(obj,OBJ_HLINE,0,0,0);
ObjectSet(obj,OBJPROP_COLOR,Gold);
hMutex = CreateMutexA(0,0,"PriceMapMutex");
}
void OnDeinit(const int reason)
{
CloseHandle(hMapFile);
Comment("");
ObjectDelete(obj);
return(0);
}
void start()
{
getsignal();
Comment("Data: ",DoubleToStr(dd,Digits));
Sleep(50);
}
void getsignal() {
WaitForSingleObject(hMutex,333);
data = MapViewOfFile(hMapFile,FILE_MAP_READ,0,0,BUF_SIZE);
dd = StrToDouble(data);
ReleaseMutex(hMutex);
UnmapViewOfFile(data);
ObjectMove(obj,0,Time[0],dd);
}
代码基本上是有效的。然而,我正面临着两个主要的问题。
问题1:
我想交换多个值( value1、value2、value3、. )。出于某种原因,我为szName="Global\\Value1"
使用的名称似乎与此无关。服务器保存该值,客户端获取它,无论我使用什么名称szName="Global\\Value1"
、szName="Global\\Value2"
或szName="Global\\Value3"
。因此,例如,在服务器代码中,我使用szName="Global\\Value1"
,在我的客户机代码中,我使用szName="Global\\Value3"
,客户机仍然获取服务器写入szName="Global\\Value1"
的值。
问题2:
我的当事人只稳定了大约5个小时。在此之后,我在客户程序中收到一条消息:
"There is a problem and the program needs to be closed..."
.
然后我关闭并重新启动我的客户,并再次工作了5个小时。
有人知道吗?
发布于 2017-05-31 05:00:25
文件介质
我同意Kernel32不是一个好的选择,如果你需要做MT4到MT4接口。原因是Kernel32是Windows专用的。EA不会在Mac上工作。此外,乱搞Kernel32 DLL可能会导致内存泄漏(例如,5小时的活动时间)。此外,它还要求用户知道如何启用DLL (您可能会惊讶于有多少用户不知道如何启用DLL)。
Recommendation:
如果您只需要相同的 MT4 exchange (图表之间的EAs),那么使用GlobalVariableGet()
、GlobalVariableSet()
等。
如果您需要在两个不同的MT4s (同一台PC上)之间进行交换--即使它跨越不同的代理MT4,那么使用文件system:Files\FilePipe.mqh
,它允许您写入公共的MT4文件夹:
#include <Files\FilePipe.mqh>
CFilePipe voPipeOut;
voPipeOut.Open("yourFileName.txt", FILE_WRITE|FILE_COMMON|FILE_BIN);
voPipeOut.WriteString("WhatEverMessage, probably some CSV value here");
voPipeOut.Close();
以及随后
CFilePipe voPipeFile;
string vsInString = "";
voPipeFile.Open("yourFileName.txt", FILE_SHARE_READ|FILE_COMMON|FILE_BIN);
voPipeFile.Seek(0,SEEK_SET);
voPipeFile.ReadString( vsInString );
voPipeFile.Close();
这样,您的EA将不依赖于DLL,也可以在广泛的环境中工作。它非常快(1毫巴管低于2毫秒)。它甚至适用于跨代理接口(交换信息提要)?在两个不同的经纪人之间)。
发布于 2017-05-28 14:47:46
最好的主意?
我能告诉您的最好的事情是,不要试图调整KERNEL32.DLL
发布的API以使其与MetaTrader终端4代码执行生态系统一起使用,而是开始设计一个专业的分布式系统,而不是将对象注入到O/S页面文件中,使用信号量和MUTEX。
除了最好的下一步:
string
声明MQL4不是一个C-lang string
,而是一个struct
!小心处理!GetLastError()
。KERNEL32.DLL
API使用的巨大风险--解除锁定的隐形安全缺陷/启用运行时劫持攻击。https://stackoverflow.com/questions/44213422
复制相似问题