首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用DLL在MQL4程序之间交换值?

如何使用DLL在MQL4程序之间交换值?
EN

Stack Overflow用户
提问于 2017-05-27 05:50:26
回答 2查看 2.2K关注 0票数 2

首先,我要说我对DLL不太了解。

我试图使用来自kernel32.dll的函数将数据从一个程序发送到另一个程序。我的程序是用MQL4编码的。

这是我为服务器部分使用的代码,它应该保存数据:

代码语言:javascript
运行
复制
#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);  
}

这就是我为我的客户端所使用的,它应该用来获取数据:

代码语言:javascript
运行
复制
#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个小时。

有人知道吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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文件夹:

代码语言:javascript
运行
复制
#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();

以及随后

代码语言:javascript
运行
复制
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毫秒)。它甚至适用于跨代理接口(交换信息提要)?在两个不同的经纪人之间)。

票数 4
EN

Stack Overflow用户

发布于 2017-05-28 14:47:46

最好的主意?

我能告诉您的最好的事情是,不要试图调整KERNEL32.DLL发布的API以使其与MetaTrader终端4代码执行生态系统一起使用,而是开始设计一个专业的分布式系统,而不是将对象注入到O/S页面文件中,使用信号量和MUTEX。

除了最好的下一步:

  • MQL4代码永远不应该阻止。将MUTEX信号转换为非阻塞状态是必须的。
  • MQL4代码/ API映射器应该尊重MQL4中的数据类型及其实际内存大小。
  • MQL4代码应该符合最近的New-MQL4规则(部分在“旧”-MQL4中)
  • string声明MQL4不是一个C-lang string,而是一个struct!小心处理!
  • 在一些地方违反了MQL4代码语法规则,只需使用MQL4进行测试
  • 当忽略名称空间边界/声明范围时,MQL4代码正在“自命不凡”
  • MQL4代码忽略潜在的错误状态,不检查任何处理此类冲突的GetLastError()
  • MQL4代码没有优雅地返回资源(忘记清除它们)
  • 提议的MQL4代码暴露了KERNEL32.DLL API使用的巨大风险--解除锁定的隐形安全缺陷/启用运行时劫持攻击。
  • 更好地使用关注点分离,使用ZeroMQ或nanomsg消息传递到(不仅) MQL4程序之间的交换值”
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44213422

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档