也许这对某人会有用,最近我一直是这么做的:
使用 CodeLight IDE 是可行的(甚至更简单)。与 Studio 相比,它不仅速度快,而且不那么 "贪婪",它接受不同的编译器,包括微软的编译器。
奇怪的是,使用 gcc 编译 DLL 更容易。在 DLL项目 的设置中指定必要的 tulchain(MT4 为 gcc32 位,MT5 为 gcc64)。仅此而已。可选择在 PostBuild 中添加 "将 DLL 复制到 MT 层次结构 "命令。
无需处理 *.def,如有必要,def 会自动生成。 顺便说一下,DllMain 完全没有必要,你可以把它扔掉 :-)更确切地说,有时需要它,但很少,而且它超出了 MT 库的需要。
还有一点--文章中没有涉及,但大家都想知道。
如果是 C++,那么也许应该有类,而且在 Mql 和 C++ 两种语言中都有。
"将 C++ 类拖入 Mql"。
1. 编写(或使用现成的)类 :-)
得到类似这样的类
#ifndef MQLPLUG_H #define MQLPLUG_H 1 #include "mql45.h" /** 将一个类 "拖入 "MT 的示例 **/ class Plug { public: Plug(); ~Plug(); mql_int OnInit(); void OnDeinit(mql_int); mql_int Sum(mql_int,mql_int); mql_double Median(MqlRates *rate); }; /* 由于 C++ 方法不能通过 DLL "拖动",而只能通过 C 函数 ,因此需要将调用委托给对象 */ 的简单函数。 MQL_API(Plug *) Plug_New(); MQL_API(void) Plug_Delete(Plug *); MQL_API(mql_int) Plug_OnInit(Plug *); MQL_API(void) Plug_OnDeinit(Plug *,mql_int); MQL_API(mql_int) Plug_Sum(Plug *,mql_int,mql_int); MQL_API(mql_double) Plug_Median(Plug *,MqlRates *rate); #endif
2.函数委托 "的实现是微不足道的--第一个参数是指向对象的指针,在函数内部我们应该检查其正确性、调用方法并捕获异常。
/// MqlPlug.cpp #include "MqlPlug.h" /*** Plug 类方法的封装函数 所有方法(_New 除外)的第一个参数都是指向 对象的指针。其他参数与方法 相同。如果传递的指针是正确的(不是 nullptr),则调用 方法,同时捕获所有异常 ***/ 。 /// 构造函数 MQL_API(Plug *) Plug_New() { try { return new Plug; } catch (...) { } return nullptr; } /// 析构函数 MQL_API(void) Plug_Delete(Plug *plug) { try { delete plug; } catch (...) { } } // 其他方法 MQL_API(mql_int) Plug_Sum(Plug *plug,mql_int one,mql_int two) { try { if (plug) return plug->Sum(one,two); } catch (...) { } return 0; } // и так далее
最后是 Mql!在导入 指令中描述了函数委托,并编写了一个类,该类只有一个字段 obj - 对象的处理程序(指针),以及调用委托的方法。
#ifdef __MQL4__ // 4k 的描述符(指针)为 32 位)。 #define HANDLE int #else // 为 5 - 64 #define HANDLE long #endif #import "Mql4Plug.dll" HANDLE Plug_New(void); void Plug_Delete(HANDLE); int Plug_OnInit(HANDLE); void Plug_OnDeinit(HANDLE,const int reason); int Plug_Sum(HANDLE,int,int); double Plug_Median(HANDLE,MqlRates &); #import class Plug { public: HANDLE obj; Plug() { obj = Plug_New(); } ~Plug() { Plug_Delete(obj); } int OnInit() { if (obj != NULL) { return Plug_OnInit(obj); } return INIT_FAILED; } void OnDeinit(const int reason) { if (obj != NULL) { Plug_OnDeinit(obj,reason); } } int Sum(int one,int two) { if (obj != NULL) { return Plug_Sum(obj,one,two); } return 0; } double Median(MqlRates &rates) { if (obj!=NULL) { return Plug_Median(obj,rates); } return EMPTY_VALUE; } };
PS/ 曾经有人提出过这样的要求,我也老老实实地试着解释了一下。但要么是我不是一个好老师,要么是我的编程水平不高 :-))但受欢迎的示例依然存在,所以我在此与大家分享
晚上好。我会试着马上回答所有问题。
...
不需要处理 *.def,如果需要,def 会自动生成。 顺便说一下,DllMain 根本不需要,你可以把它扔掉 :-)更确切地说,有时需要它,但很少,而且它超出了 MT 库的需要。
本文讨论的不是如何生成定义文件、是否可以生成定义文件、使用什么工具生成定义文件。文章讨论的是需要它做什么,它在 VS 中可以用来做什么,会产生什么结果。至于如何制作、用什么制作、何时制作,这些都不重要。
关于 DllMain。理论上你是对的。是的,你可以不使用这个函数。我知道在一些工具中,即使存在 DllMain 也不会被调用。但我完全不同意您断然下的结论,即它 "超越了边界"。我确信,这样的结论应该由开发人员自己做出,因为他要对结果负责。如果他需要,可以在 DllMain 中调用。如果他不想这样做,可以编写一个单独的可导出函数。就我个人而言,我觉得自己没有足够的能力轻易剥夺他的这一附加功能。
还有一点--文章中没有涉及,但有需求。
如果是 C++,那么也许应该在 Mql 和 C++ 两种语言中都有类。
"将 C++ 类拖入 Mql"。
绝对没有必要导出类。))感谢您提到这一功能,并特别感谢您提供的示例。就我个人而言,我从未想过要做这样的事情,更不会向新手开发者推荐这样的技术。看看这段代码的人为性和不合理性。是什么原因让开发人员以如此奇怪的方式处理指针呢?换句话说,如果这段代码不会崩溃,那么作为一个理论示例它是有趣的,但从实践角度来看--几乎不可能)我想多说几句,在我看来,如果开发人员需要这样的导出,那么他很有可能在设计上犯了错误。 此外,我想提请大家注意的是,这篇文章大约有一半的篇幅都在讨论结构,而这些结构 "几乎都是类"。我们应该就此打住,不要步论坛上某些同行的后尘,他们很乐意将所有 C++17 都塞进 MQL 中))).
我没跟你争论;-)
所以--一些我记得的笔记,也许会对某人有用。
谢谢,会有用的。
但遗憾的是,这样的好例子通常都在论坛主题中,很难找到,唉,我自己也罪过 ))))。
如果您不懒惰,您应该把这些优秀的例子放到您的博客中,至少您有可能更快地找到它们,但这也不是事实 (((( - MQL 具有惊人的可能性,但有时自己谷歌一下,找到一个现成的例子会更快...顺便说一下,本论坛的谷歌索引非常好,几乎所有关于神经网络主题的查询都能找到 MQL 文章;)
新文章 10 分钟掌握 MQL5 的 DLL(第二部分):使用 Visual Studio 2017 创建已发布:
初版文章依然具有其相关性,因此如果您对此主题感兴趣,请务必阅读第一篇文章。 从初版起已经过了很久时间,而当前的 Visual Studio 2017 具有全新的界面。 MetaTrader 5 平台也拥有了诸多新功能。 本文提供了开发 DLL 项目各个阶段的描述,以及如何设置 DLL 并与 MetaTrader 5 工具进行交互。
创建一个简单的 DLL
整个过程已在初版文章中有所描述。 如今我们再次研究软件的更新和变化。
运行 Visual Studio 2017,并导航到文件 -> 新建 -> 项目。 在新项目窗口的左侧,展开 Visual C++ 列表,然后从中选择 Windows 桌面。 在中间部分选择 Windows 桌面向导那一行。 使用底部的输入字段,您可以编辑项目名称(建议您设置有意义的名称),并设置项目位置(推荐保留建议值)。 单击“确定”,然后继续下一个窗口:
从下拉列表中选择动态链接库(.dll),然后选中“导出符号”。 勾选此项是可选的,但建议初学者这样做。 在这种情况下,演示代码将添加到项目文件中。 这段代码可以查看,之后删除或注释。 单击“确定”将创建项目文件,然后可以对其进行编辑。 不过,我们先要考虑项目设置。 首先,请记住,MetaTrader 5 仅可协同 64 位函数库操作。 如果您尝试连接 32 位 DLL,您将收到以下消息:
'E:\...\MQL5\Libraries\Project2.dll' is not 64-bit version
Cannot load 'E:\MetaTrader 5\MQL5\Libraries\Project2.dll' [193]
因此,您将无法使用此函数库。
作者:Andrei Novichkov