首页 / 交易学院 / 小布知识库 / 用 EX5 库封装与共享代码:导出函数、隐藏类实现、可被继承
用 EX5 库封装与共享代码:导出函数、隐藏类实现、可被继承
📦

用 EX5 库封装与共享代码:导出函数、隐藏类实现、可被继承

MQL5 编程 难度 · 进阶 2011 13 分钟阅读
EX5 库exportimport类封装虚函数代码共享

当你写出好用的函数或类,想共享给团队或对外发布,又不想公开实现细节——EX5 库就是 MQL5 的答案。编译进 .ex5 后,调用方只能看到接口、看不到源码。本文从“导出/导入函数”讲起,再到“把整个类的实现藏进库里”,最后到“库类还能被外部继承”,一步步把封装与共享讲透。

一、函数的导出与导入

导出函数要满足三件事:源文件扩展名必须是 .mq5(不是 .mqh)才能编进 .ex5;文件里加 #property library 预处理指令;在函数声明前加 export 关键字。编译后得到 library.ex5,其中的 libfunc 就能被别的程序用。导入则靠 #import 指令:在目标文件里写 #import "library.ex5" 然后声明函数原型,编译器会在 MQL5\Libraries 文件夹找 .ex5,找不到就写相对路径。

// library.mq5 —— 带 #property library 与 export
#property library
int libfunc(int a, int b) export
  {
   int c=a+b;
   Print("a+b="+string(c));
   return(c);
  }

// uses.mq5 —— 导入并使用
#import "library.ex5"
   int libfunc(int a, int b);
#import
void OnStart() { libfunc(1,2); }

二、实战:把 GUI 绘图函数做成库

文中用一个 Graph.mq5 库示范:它导出在图表上画按钮、编辑框、标签、矩形标签的函数(如 SetEdit、SetLabel、SetButton、HideChart),目标 EA(Spiro.mq5)只需 #import "Graph.ex5" 声明原型就能直接调用,把绘图细节完全藏进库。这正是一开始说的价值:共享能力、隐藏实现。函数不仅能导入 .mq5,也能导入 .mqh,方便做成公共头。

易错点:导入时声明的函数签名(参数类型、顺序、默认值)必须和库里 export 的一字不差,否则编译或运行期行为错乱。改库函数签名时,记得同步更新所有 #import 处的原型声明。

三、类实现怎么藏:接口类 + 虚函数

MQL5 不能直接 export 一整个类,于是作者用“多态 + 虚函数”绕过去:把类拆成两个——公开的接口类(如 CSpiro,只留变量和虚函数声明,放在 .mqh 头文件)和隐藏的实现类(ISpiro,继承 CSpiro,真正实现全在 .ex5 里)。再导出一个工厂函数 iSpiro() export,返回一个 new ISpiro 实例。调用方拿到的类型是 CSpiro*,永远触不到 ISpiro 的具体代码。

四、导出类的继承:库类也能被扩展

MetaQuotes 后来支持了“直接继承 ex5 库里的类”,这是更进一步的玩法。意味着你发布的库类,别人可以像普通类一样派生出子类、重写虚函数,而不必知道内部实现。这让 EX5 库从“黑盒工具”变成“可扩展框架”——适合做插件体系或平台级 SDK。

// 接口头 Spiro.mqh(公开)
class CSpiro
  {
public:
   string  m_sID; int m_x0,m_y0; color m_clr;
   double  m_R,m_r,m_D,m_dAlfa,m_nRotate;
   CSpiro() {}; ~CSpiro() {};
   virtual void Init(int ax0,int ay0,color aclr,string asID) { };
   virtual void SetData(double aR,double ar,double aD,double adA,double an) { };
  };

// 隐藏实现 ISpiro.mq5 里:CSpiro *iSpiro() export { return(new ISpiro); }

五、EX5 库的发布与注意事项

发布库时,把 .ex5 与公开 .mqh 头一起交给调用方,.ex5 里的实现就是黑盒。要注意:导出/导入有官方限制(如参数类型支持范围、字符串传递方式),写之前务必查文档的“导出/导入”章节。另外 .ex5 是编译产物,跨平台/跨版本 MT5 要注意兼容性——同一编译环境产出最稳。

封装哲学:EX5 库让你“卖能力不卖秘密”。函数级用 export/#import 足够;类级用“接口类+虚函数+iSpiro 工厂”黑科技;要可扩展就开放继承。它天然适合团队分工、外包模块、以及对外授权的算法 SDK。

六、小结

EX5 库是 MQL5 里“共享但不暴露”的标准机制:函数用 #property library + export 导出、#import 导入;类用“公开接口类(虚函数)+ 隐藏实现类 + 工厂函数 iSpiro()”把实现藏进 .ex5,还能被外部继承扩展。它把你的专有算法变成黑盒 SDK,是团队分工与对外授权的利器。记住导入签名要严丝合缝、发布时附带公开头文件,封装就能既安全又顺手。

常见问题

三件事:源文件用 .mq5 扩展名(非 .mqh)以编进 .ex5;文件加 #property library 预处理指令;在函数声明前加 export 关键字。编译后得到 library.ex5,其中的函数即可被别的程序导入使用。
用 #import 指令:在目标文件写 #import "library.ex5" 然后声明函数原型(int libfunc(int a,int b);),再以 #import 结束。编译器在 MQL5\Libraries 找 .ex5,找不到要写相对路径。函数也能导入 .mqh 头方便复用。
用“接口类+虚函数”黑科技:把类拆成公开接口类(CSpiro,只留变量和虚函数声明,放 .mqh 头)和隐藏实现类(ISpiro 继承它,真正实现在 .ex5 内),再导出一个工厂函数 iSpiro() export 返回 new ISpiro。调用方只拿到 CSpiro*,触不到具体代码。
可以。MetaQuotes 支持直接继承 ex5 库里的类,别人能像普通类一样派生子类、重写虚函数而不必知道内部实现。这让 EX5 库从黑盒工具升级为可扩展框架,适合做插件体系或平台级 SDK。
把 .ex5 与公开 .mqh 头一起交付,实现即黑盒;导入处函数签名必须与库里 export 一字不差;导出/导入有官方类型限制,写前查文档;.ex5 是编译产物,尽量同编译环境产出以保证跨版本兼容。