资料库: 无需 DLL 的文件映射 - 页 11 1...456789101112 新评论 Алексей Барбашин 2017.10.23 22:17 #101 o_o:不是关闭记录,而是关闭并删除文件。这就是为什么 你试图打开的东西已经不存在了。通过查看库代码,我发现不仅在直接调用 CMemMapFile 类的 Close() 函数时文件会被删除,而且在删除指向该类对象的指针时文件也会被删除,因为该函数是在类的析构函数中调用的。我有点困惑。原来,如果在不同的调用上下文(作用域)中使用写文件和读取文件,就无法使用创建类对象的动态方法。例如,终端的一个图表向文件写入数据,第二个图表读取数据并删除该文件。事实证明,对象变量应始终保持在全局级别,这样文件才不会被强制删除。另外,我们还不清楚是否可以不指定读取数据的大小。也就是说,在写入数据时,我们知道数据的大小,但在另一个图表上读取数据时,我们可能事先不知道数据的大小,例如字符串值。可能是我误解了什么,也可能是库中还有其他需要调整的地方。是我不好。我重新检查了一下,没有使用指针,因此也没有使用删除。在这种情况下,当离开作用域(从函数)时,类对象的局部变量将被销毁,而无需明确调用析构函数。关于接收方接收数据的大小,还有一个问题。 Алексей Барбашин 2017.10.24 10:03 #102 fxsaber:感谢作者提供该库!我制作了用于传输任何数据的函数。下面的脚本展示了它们在刻度线示例中的工作情况结果超级棒!通过与您的代码进行类比,我简化了库的使用。 fxsaber 2017.11.30 14:20 #103 MT4 价格转移示例 交易、自动交易系统和交易策略测试论坛 Metatrader 4 的命名管道 fxsaber, 2017.11.30 14:18 Exchange_Data.mqh#include <MemMapLib.mqh> #include <TypeToBytes.mqh> template <typename T> class EXCHANGE_DATA { private: CMemMapFile* FileMemory; public: // 为数据分配指定长度的内存 EXCHANGE_DATA( const int Amount, const bool ModeCreate = false, string FileName = "Local\\test" ) { // FileName += _Symbol; this.FileMemory = new CMemMapFile; if (this.FileMemory.Open(FileName, sizeof(T) * Amount + sizeof(int) + HEAD_MEM, ModeCreate ? modeCreate : modeOpen) != 0) { Alert("FileMemory.Open - ERROR!"); delete &this; } } ~EXCHANGE_DATA( void ) { this.FileMemory.Close(); delete this.FileMemory; } // 将数据写入内存 void DataSave( const T &Data[], const bool FromBegin = true ) const { const int Size = ::ArraySize(Data) * sizeof(T); uchar Bytes[]; _ArrayCopy(Bytes, _R(Size).Bytes); // 记录数量 _ArrayCopy(Bytes, _R(Data).Bytes, sizeof(int)); // 记录数据 if (FromBegin) this.FileMemory.Seek(0, SEEK_SET); this.FileMemory.Write(Bytes, ::ArraySize(Bytes)); // 将所有内容转入内存 return; } // 从内存中读取数据 int DataLoad( T &Data[], const bool FromBegin = true ) const { if (FromBegin) this.FileMemory.Seek(0, SEEK_SET); uchar Bytes[]; this.FileMemory.Read(Bytes, sizeof(int)); // 从内存中读取数据量 this.FileMemory.Read(Bytes, _R(Bytes)[0]); // 获取数据本身 _ArrayCopy(Data, Bytes); // 将数据转入数组 return(::ArraySize(Data)); } };PriceGiver.mq4#property strict #include "Exchange_Data.mqh" #define AMOUNT 100 EXCHANGE_DATA<MqlTick> ExchangeTicks(AMOUNT, true); const bool Init = EventSetMillisecondTimer(100); void OnTimer( void ) { static MqlTick Ticks[1]; if (SymbolInfoTick(_Symbol, Ticks[0])) ExchangeTicks.DataSave(Ticks); }PriceTaker.mq4#property strict #include "Exchange_Data.mqh" #define AMOUNT 100 EXCHANGE_DATA<MqlTick> ExchangeTicks(AMOUNT); const bool Init = EventSetMillisecondTimer(100); #define TOSTRING(A) (#A + " = " + (string)(A) + " ") void OnTimer( void ) { static MqlTick PrevTick = {0}; MqlTick Ticks[]; if ((ExchangeTicks.DataLoad(Ticks) > 0) && ((Ticks[0].bid != PrevTick.bid) || (Ticks[0].ask != PrevTick.ask))) { Print(TOSTRING(Ticks[0].time) + TOSTRING(Ticks[0].bid) + TOSTRING(Ticks[0].ask)); PrevTick = Ticks[0]; } }运行PriceGiver.ex4 和PriceTaker. ex4。结果2017.11.30 15:13:55.101 Expert PriceGiver EURUSD,M1: removed 2017.11.30 15:13:55.091 PriceGiver EURUSD,M1: uninit reason 1 2017.11.30 15:13:51.006 Expert PriceTaker GBPAUD,M1: removed 2017.11.30 15:13:50.996 PriceTaker GBPAUD,M1: uninit reason 1 2017.11.30 15:13:49.168 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:41 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 2017.11.30 15:13:48.838 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:41 Ticks[0].bid = 1.18484 Ticks[0].ask = 1.18489 2017.11.30 15:13:48.186 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:40 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 2017.11.30 15:13:47.751 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:40 Ticks[0].bid = 1.18484 Ticks[0].ask = 1.18488 2017.11.30 15:13:42.178 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:34 Ticks[0].bid = 1.18485 Ticks[0].ask = 1.18489 2017.11.30 15:13:41.633 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:34 Ticks[0].bid = 1.18484 Ticks[0].ask = 1.18488 2017.11.30 15:13:37.588 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:30 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 2017.11.30 15:13:36.175 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:28 Ticks[0].bid = 1.18481 Ticks[0].ask = 1.18485 2017.11.30 15:13:30.717 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:23 Ticks[0].bid = 1.18482 Ticks[0].ask = 1.18486 2017.11.30 15:13:29.514 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:22 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 2017.11.30 15:13:27.324 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:19 Ticks[0].bid = 1.1848 Ticks[0].ask = 1.18484 2017.11.30 15:13:26.994 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:19 Ticks[0].bid = 1.18482 Ticks[0].ask = 1.18486 2017.11.30 15:13:26.012 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:18 Ticks[0].bid = 1.18481 Ticks[0].ask = 1.18485 2017.11.30 15:13:25.584 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:18 Ticks[0].bid = 1.18482 Ticks[0].ask = 1.18486 2017.11.30 15:13:25.254 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:16 Ticks[0].bid = 1.18481 Ticks[0].ask = 1.18485 2017.11.30 15:13:25.147 PriceTaker GBPAUD,M1: initialized 2017.11.30 15:13:24.049 Expert Sparring\PriceTaker GBPAUD,M1: loaded successfully 2017.11.30 15:13:21.157 PriceGiver EURUSD,M1: initialized 2017.11.30 15:13:19.617 Expert Sparring\PriceGiver EURUSD,M1: loaded successfully Alexey Navoykov 2018.06.01 07:01 #104 库中的 CMemMapFile::Open 方法有一个小错误,它应该返回文件句柄(HANDLE64 类型),但却返回 0 或错误代码。此外,读取和写入方法 CMemMapApi::Write 和 CMemMapApi::Read 由于某种原因会重复复制数据(字节被循环遍历!),而且文件会被整体覆盖/读取,尽管只需要指定的部分。总的来说,我让它们看起来很正常,不必要的内容都注释掉了://------------------------------------------------------------------ Write int CMemMapApi::Write(HANDLE64 hmem, const uchar &buf[], DWORD pos, int sz, DWORD &err) // 将指定字节数写入内存 { if (hmem==NULL) return(-1); PBYTE64 view=ViewFile(hmem, err); if (view==0 || err!=0) return(-1); // 如果未打开 DWORD size=GetSize(hmem, err); if (pos+sz>size) { UnViewFile(view); return(-2); }; // 如果尺寸较小,则退出 /* uchar src[]; ArrayResize(src, size); memcpyX(src, view, size); // took bytebuffer for(int i=0. i<sz; i++);i<sz; i++) src[pos+i+HEAD_MEM]=buf[i]; // 写入内存 memcpyX(view, src, size); // 复制回 */ memcpyX(view+HEAD_MEM+pos, buf, sz); UnViewFile(view); // 关闭视图 return(0); // 返回 OK。 } //------------------------------------------------------------------ Read int CMemMapApi::Read(HANDLE64 hmem, uchar &buf[], DWORD pos, int sz, DWORD &err) // 从内存中读取指定的字节数 { if (hmem==NULL) return(-1); PBYTE64 view=ViewFile(hmem, err); if (view==0 || err!=0) return(-1); // 如果未打开 DWORD size=GetSize(hmem, err); // 得到了尺寸 /* uchar src[]; ArrayResize(src, size); memcpyX(src, view, size); // took bytebuffer ArrayResize(buf, sz); int i=0; for(i=0; i<sz && pos+i<size; i++) buf[i]=src[pos+i+HEAD_MEM]; // 读取字节 */ sz= fmin(sz, size-pos); ArrayResize(buf, sz); memcpyX(buf, view+HEAD_MEM+pos, sz); UnViewFile(view); // 关闭视图 return sz; // 复制的字节数 } 为了使第一个函数能够编译,需要在memcpyX 和memcpy 函数中为数组设置const,而作者并没有设置。 pushdib 2018.06.04 20:06 #105 复制大尺寸时出错,原因是在 dwMaximumSizeHigh 中传递了 0 if (mode==modeCreate) hmem=CreateFileMappingWX(INVALID_HANDLE_VALUE64, NULL, PAGE_READWRITE, 0, size + HEAD_MEM, path); // 创建一个内存对象 这样修复: if (mode==modeCreate) hmem=CreateFileMappingWX(INVALID_HANDLE_VALUE64, NULL, PAGE_READWRITE, size + HEAD_MEM, size + HEAD_MEM, path); // 创建一个内存对象 该文件大小为 6 MB,传输没有问题: void OnStart() { int bars = Bars(_Symbol, _Period); MqlRates rates[]; ArraySetAsSeries(rates, true); CopyRates(NULL, 0, 0, bars, rates); int size = ArraySize(rates) * sizeof(MqlRates); uchar data[]; _ArrayCopy(data, rates); CMemMapFile *hmem = new CMemMapFile(); hmem.Open("test", size, modeCreate); hmem.Write(data, size); hmem.Close(); delete hmem; Print(size); } TheXpert 2018.06.04 20:27 #106 pushdib:更正如下正确传递 8 字节大小的高 4 字节。 pushdib 2018.06.04 20:52 #107 好了,现在我们有了 C# 程序中的所有命令,我们可以使用 LINQ 分析我们需要的一切。 但有一个问题,如何组织终端和应用程序之间的命令机制。 从终端:新建蜡烛,新建数据--获取文件 从应用程序:计算完成,获取结果(在图表上绘图,打开交易)。 有谁在终端和代码之间的交互执行方面有经验? Dmitriy Skub 2018.06.04 21:24 #108 pushdib:好了,现在我们有了 C# 程序中的所有数据,可以使用 LINQ 完美地分析一切了。 但还有一个问题,那就是如何组织终端和应用程序之间的命令机制。 从终端:新建蜡烛、新建速率--获取文件从应用程序:计算完成,获取结果(在图表上绘制,打开交易)。有没有人有过这种实现终端和代码之间交互的经验? 我都是通过 pip 实现的--工作起来就像发条一样。 BillionerClub 2019.02.05 18:20 #109 这真是太棒了,感谢您的辛勤劳动!-)).我不得不同时学习如何处理二进制文件,但这是值得的。 pivomoe 2019.06.20 15:23 #110 请告知在这种情况下该怎么办。 1. 我在内存中打开了一个 100 字节的新文件。 2.我向其中写入了 100 字节。 3.我在另一个智能交易系统中读取了 100 字节。一切正常。 4.现在如何向同一文件写入 50 或 200 字节? 1...456789101112 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
不是关闭记录,而是关闭并删除文件。
这就是为什么
你试图打开的东西已经不存在了。通过查看库代码,我发现不仅在直接调用 CMemMapFile 类的 Close() 函数时文件会被删除,而且在删除指向该类对象的指针时文件也会被删除,因为该函数是在类的析构函数中调用的。我有点困惑。原来,如果在不同的调用上下文(作用域)中使用写文件和读取文件,就无法使用创建类对象的动态方法。例如,终端的一个图表向文件写入数据,第二个图表读取数据并删除该文件。事实证明,对象变量应始终保持在全局级别,这样文件才不会被强制删除。另外,我们还不清楚是否可以不指定读取数据的大小。也就是说,在写入数据时,我们知道数据的大小,但在另一个图表上读取数据时,我们可能事先不知道数据的大小,例如字符串值。可能是我误解了什么,也可能是库中还有其他需要调整的地方。
是我不好。我重新检查了一下,没有使用指针,因此也没有使用删除。在这种情况下,当离开作用域(从函数)时,类对象的局部变量将被销毁,而无需明确调用析构函数。
关于接收方接收数据的大小,还有一个问题。
感谢作者提供该库!
我制作了用于传输任何数据的函数。下面的脚本展示了它们在刻度线示例中的工作情况
结果
超级棒!通过与您的代码进行类比,我简化了库的使用。
交易、自动交易系统和交易策略测试论坛
Metatrader 4 的命名管道
fxsaber, 2017.11.30 14:18
Exchange_Data.mqh
PriceGiver.mq4
PriceTaker.mq4
运行PriceGiver.ex4 和PriceTaker. ex4。
结果
库中的 CMemMapFile::Open 方法有一个小错误,它应该返回文件句柄(HANDLE64 类型),但却返回 0 或错误代码。
此外,读取和写入方法 CMemMapApi::Write 和 CMemMapApi::Read 由于某种原因会重复复制数据(字节被循环遍历!),而且文件会被整体覆盖/读取,尽管只需要指定的部分。
总的来说,我让它们看起来很正常,不必要的内容都注释掉了:
为了使第一个函数能够编译,需要在memcpyX 和memcpy 函数中为数组设置const,而作者并没有设置。复制大尺寸时出错,原因是在 dwMaximumSizeHigh 中传递了 0
这样修复:
该文件大小为 6 MB,传输没有问题:
更正如下
正确传递 8 字节大小的高 4 字节。
好了,现在我们有了 C# 程序中的所有命令,我们可以使用 LINQ 分析我们需要的一切。
但有一个问题,如何组织终端和应用程序之间的命令机制。
从终端:新建蜡烛,新建数据--获取文件
从应用程序:计算完成,获取结果(在图表上绘图,打开交易)。
有谁在终端和代码之间的交互执行方面有经验?
好了,现在我们有了 C# 程序中的所有数据,可以使用 LINQ 完美地分析一切了。
但还有一个问题,那就是如何组织终端和应用程序之间的命令机制。
从终端:新建蜡烛、新建速率--获取文件
从应用程序:计算完成,获取结果(在图表上绘制,打开交易)。
有没有人有过这种实现终端和代码之间交互的经验?
请告知在这种情况下该怎么办。
1. 我在内存中打开了一个 100 字节的新文件。
2.我向其中写入了 100 字节。
3.我在另一个智能交易系统中读取了 100 字节。一切正常。
4.现在如何向同一文件写入 50 或 200 字节?