有些开发者写了一段很实用的通用模块:可能是数据整理函数、日志工具、字符串处理组件,或者一套供多个 EA 和指标重复调用的内部能力。项目做到一定阶段,合作方希望在自己的程序里调用这些功能,但并不一定需要看到模块内部每一行代码。
这时候,问题就来了。
如果直接把完整 .mq5 源码发出去,对方当然可以查看和继续修改,但原本只想开放“调用能力”的合作,很容易变成源码边界说不清;如果只给一个 .ex5 文件,对方虽然拿到了可执行模块,却不知道应该调用哪些函数、传入什么参数、返回什么结果。
合作方需要的是调用能力,不一定意味着你要把每一行实现细节都交出去。
MetaEditor 提供的 Generate Include File 功能,正是为这类模块化协作场景准备的。它可以根据源文件中明确导出的函数,生成一个 .mqh 接口文件。接口文件负责告诉调用方“有哪些功能可以使用、怎样调用”,而相应的 .ex5 模块则负责真正执行这些功能。
可以先用一句话理解:MQH 更像说明如何连接模块的接口,EX5 才承担实际执行的部分。
本文将从实际协作角度说明 MetaEditor MQH、MQL5 Include 文件、EX5 模块 与 MQL5 源码保护 之间的关系。平台功能说明可参考 MetaTrader 5官网。文章只讨论结构、复用和授权边界,不提供交易策略实现,也不讨论破解、反编译或绕过 EX5 保护的方法。
一、MQH Include 文件是什么?
在 MQL5 项目里,.mqh 通常被称为 Include 文件 或头文件。
对刚开始做模块化开发的用户来说,可以把它理解成:供其他程序引入使用的一份“说明与连接文件”。
普通情况下,MQH 可能保存:
- 函数声明;
- 类或结构定义;
- 枚举和常量;
- 可复用的辅助代码;
- 供多个 MQ5 文件共同使用的公共内容。
而在本文讨论的场景中,MetaEditor 自动生成的 MQH 接口文件,重点并不是把内部实现代码都复制进去,而是描述一个 EX5 模块对外开放的函数。
例如,一个合作模块对外只开放三种能力:读取某类计算结果;检查某个输入格式;返回某种状态信息。
调用方只需要知道这三个函数的名称、参数和返回类型,并配合相应的 EX5 模块使用即可;至于模块内部具体怎样完成计算,不一定需要直接公开。
这就是“接口”和“实现”分开的基本思路。
二、MQH、MQ5 和 EX5 有什么区别?
新手最容易混淆的,是这三种文件都出现在 MQL5 开发流程里,却承担着不同角色。
MQ5:主源码文件
.mq5 是 EA、指标、脚本或库模块的主要源代码文件。
它通常包含真正的程序实现,例如具体函数逻辑、内部处理过程、数据计算方法、事件入口,以及调试和维护所需内容。
拥有 MQ5 源码的人,在获得相应授权后,可以阅读、修改和重新编译程序。
EX5:编译后的可执行模块
.ex5 是源码经过 MetaEditor 编译后生成的运行文件。
MT5 平台可以加载 EX5,其他 MQL5 程序也可以在符合规则的情况下调用 EX5 库导出的函数。
EX5 更像成品模块:它承担运行功能,但不能替代你自己保留的源码,也不等于向使用方开放继续修改权限。关于 MQ5 编译为 EX5 的基础流程,可参考 MQL5 Wizard 与 EA 编译入门。
MQH:告诉调用方如何使用模块的接口文件
在模块共享场景中,.mqh 可以承担接口说明的作用。它告诉调用方:需要导入哪个 EX5 模块;哪些函数可以调用;函数需要哪些参数;返回什么类型的数据。
简单比喻:
- MQ5 像厨房里的完整配方和制作过程;
- EX5 像已经完成并能工作的机器;
- MQH 像机器的操作面板说明和接口规格。
调用方可以按接口使用机器,但并不因此自动获得内部制作方法。
三、MetaEditor 的 Generate Include File 是什么?
Generate Include File 是 MetaEditor 中用于生成 MQH 接口文件的功能。
当你打开一个 MQ5 源文件,并且其中存在明确标记为对外导出的函数时,MetaEditor 可以根据这些函数自动生成一个 MQH 文件。
通常入口为:Tools / 工具 → Generate Include File
生成后的 MQH 文件会包含:
- 指向相应 EX5 模块的 #import 声明;
- 从当前源码中识别出的导出函数声明;
- 供其他 MQL5 程序调用该模块时使用的接口信息。
这一步的价值在于,开发者不需要手动重新抄写每个函数接口,也能减少调用方和实现方之间因函数名称、参数类型写错而产生的问题。
不过,它不是对任何文件都能自动生成有效接口。需要注意:
- 当前打开的应是 MQ5 主文件,而不是普通 MQH 接口文件;
- 文件中需要存在可被识别的导出函数;
- 如果没有导出函数,MetaEditor 会提示没有可生成内容;
- 生成 MQH 以后,仍然必须配合相应 EX5 模块才能真正执行功能。
四、哪些函数可以生成到接口文件中?
Generate Include File 不会把源文件中的所有内部函数都放进接口文件。它只面向那些被开发者明确标记为可导出的函数。
在 MQL5 库模块中,准备开放给其他程序调用的函数,需要使用 export 修饰符进行标记。
通俗来说,export 的意义就是:“这个函数属于我愿意提供给外部模块调用的接口。”
这样做的好处是,开发者可以主动划分边界:内部辅助函数继续留在模块内部;只有确实需要合作方调用的能力才对外开放;接口文件只描述开放功能,而不会自动暴露全部实现逻辑。
这里还有几个边界值得知道:
- 可以导出函数;
- 不能直接把整个类或整个结构作为完整模块接口一次性导出;
- 函数模板不适合直接作为导出接口;
- 接口参数和返回类型必须与实际 EX5 模块中的导出函数保持一致。
这也是为什么共享模块时,不应随意修改接口文件内容而忘记同步更新 EX5。如果调用方使用的 MQH 声明与实际 EX5 导出接口不一致,程序运行时就可能出现找不到函数或行为异常的问题。
五、为什么 MQH 文件必须配合相应的 EX5 模块使用?
有些新手拿到 MQH 文件后,会以为把它放进 Include 目录,程序就已经拥有了全部功能。
其实不是这样。
自动生成的 MQH 接口文件,主要承担的是“连接说明”作用。它会告诉调用程序应该从哪个 EX5 模块导入哪些函数,但真正的计算与执行逻辑仍然存在于对应的 EX5 文件中。
换句话说:
- 没有 MQH,调用方可能不知道怎样正确调用模块;
- 没有 EX5,MQH 只有接口声明,没有真正可执行的功能。
这就像你拿到了一份设备操作手册,却没有拿到设备本身;或者拿到了设备,却没有接口说明,不知道按钮和插口分别怎样使用。
因此,向合作方交付模块时,通常需要同时明确提供:生成的 MQH 接口文件;对应版本的 EX5 模块文件;必要的使用说明;文件放置位置;版本号与依赖要求;允许使用的范围。
特别需要注意的是,MQH 与 EX5 应当属于同一套接口版本。如果开发者更新了 EX5 中导出的函数,却没有同步更新 MQH,合作方的程序可能编译通过后仍在运行时出错,或者直接无法加载所需函数。
六、如果源文件位于 Libraries 目录,生成路径有什么不同?
MQL5 中专门预留了 MQL5/Libraries 目录,用于存放可供其他程序调用的库模块。
如果你的源文件位于 MQL5/Libraries 或其子目录中,那么使用 Generate Include File 时,MetaEditor 通常会将生成的 MQH 接口文件放到 MQL5/Include 目录中,同时生成的 #import 路径会按照该模块在 Libraries 目录下的相对位置写入。
举个结构层面的例子:
- 实现模块位于 MQL5/Libraries/Tools/UtilityModule.mq5;
- 编译后形成对应的 EX5 库模块;
- 自动生成的接口文件会进入 Include 体系,供其他程序通过 #include 引入;
- 接口内部则指向 Libraries 下对应的 EX5 模块路径。
如果当前 MQ5 文件不在 Libraries 目录中,生成的 MQH 通常会放在与源文件相同的位置,导入信息也会采用相应的模块名称。
对新手来说,不需要死记所有路径细节,但应建立一个清楚习惯:准备作为共享库使用的模块,最好从一开始就规划好 Libraries 与 Include 的目录关系,避免文件后来散落各处。
七、这种方式适合哪些模块复用与协作场景?
MQH 接口文件加 EX5 模块的方式,适合“需要调用功能,但不需要直接开放完整实现”的合作场景。
通用工具函数模块
例如你写了一组通用的数据格式化、状态检查、日志输出或基础计算函数,希望多个项目复用。这类能力可以整理为库模块,只开放必要函数接口,减少每个项目重复复制源码。
合作项目中的边界模块
多人协作时,有些成员只需要使用一个模块输出的结果,而不负责维护模块内部实现。这时,明确的接口文件比直接把整套源码混在一起更容易管理。
向合作方提供可调用组件
如果合作方需要在自己的 MQL5 程序中调用你开发的组件,而合作范围并不包括查看全部源码,那么提供 MQH 接口文件与相应 EX5 模块,可以让调用边界更清晰。
需要保留内部实现细节的功能封装
有些开发者可能愿意公开函数用途和参数规则,但不希望立即公开内部实现过程。这种情况下,接口与实现分离可以作为技术交付中的一种方式。
不过,需要明确:这种方式适合你本人拥有授权、并且双方已经谈清楚使用范围的模块。它不是用来处理来源不明代码,更不是用来重新包装未经授权的商业程序。
八、它为什么不等于完整源码授权?
生成 MQH 接口文件,并提供对应 EX5 模块,并不意味着你已经向对方交付完整源码。
接口共享通常只表示:对方知道哪些函数可以调用;对方可以在约定环境中使用这些功能;对方获得的是模块使用能力,而不是所有内部实现细节。
但技术文件本身不会自动写清楚法律或商业授权范围。你仍然需要在合作前明确:是否仅限项目内部使用;是否允许转发给第三方;是否允许嵌入其他产品;是否允许修改接口文件;是否提供后续升级版本;是否允许二次分发;源码是否属于交付内容;接口发生变化后如何处理兼容问题。
源码保护不是不合作,而是先把共享范围讲清楚。
如果合作方确实需要修改模块内部逻辑,那么仅提供 MQH 和 EX5 可能不够,双方应进一步约定是否交付源码,以及源码交付后的使用边界。也可结合 MQL5 Cloud Protector 与 EX5 交付边界 理解成品文件保护与技术授权的区别。
九、分享模块前应该确认哪些版本、依赖和授权问题?
接口式协作看起来简洁,但如果版本和依赖管理做不好,也很容易让双方反复排错。
先确认接口版本
MQH 文件与 EX5 模块必须对应。建议在交付时注明模块名称、版本号、生成日期、对应的接口文件,以及兼容的 MT5 / MQL5 环境说明。
说明目录位置
合作方需要知道 MQH 放到哪里、EX5 放到哪里、主程序怎样引入接口,以及是否还依赖其他模块。只给文件而不给目录说明,很容易让调用方误以为程序本身有问题,实际只是文件没有放到可搜索的位置。
确认是否还有外部依赖
如果 EX5 模块还依赖其他文件、权限或外部组件,应提前说明。不要等到对方加载失败后,才发现还缺少某个必要模块。
确认代码分享权限
在提供任何文件前,都要确认你有权进行交付,尤其是委托开发项目、团队共同维护模块、含有第三方库的项目、商业源码或客户保密代码。即使你可以生成 MQH 或编译 EX5,也不代表你天然拥有向外分享的权利。
保留自己的源码与历史版本
提供 EX5 和 MQH 给合作方之前,开发者自己应保留完整 MQ5 源码、MQH 相关自有文件、当前编译版本、接口变更记录、必要测试说明,以及版本管理备份。接口交付方便别人调用,但不能替代你自己对源码的长期维护。
十、新手做模块化协作时常见的误区
误区一:把 MQH 当成完整程序
MQH 接口文件描述的是调用方式,并不等于它自己就包含全部可执行逻辑。缺少对应 EX5,接口无法独立完成模块功能。
误区二:生成接口后就可以删除源码
这是非常危险的想法。EX5 和生成的 MQH 都不能替代你自己保存的 MQ5 实现源码。后续修改、修复和重新发布仍然需要源文件。
误区三:接口没变,EX5 随便换版本也没关系
如果 EX5 内部导出函数的签名、参数、返回类型或兼容关系发生变化,而 MQH 没有同步,调用程序可能出现运行错误。接口和执行模块必须成套管理。
误区四:提供 EX5 就不需要说明授权
文件没有直接公开源码,不代表使用范围天然明确。是否允许转发、嵌入、商用、二次分发或长期使用,仍然应提前说明。
误区五:把未经授权的代码包装成自己的模块
无论是生成 MQH、编译 EX5,还是增加其他保护,都不会改变原始代码的授权归属。来源不明或无权传播的程序,不应被重新包装后交给别人。
十一、模块共享前检查清单
- 当前模块是否属于我有权交付或共享的内容?
- 合作方真正需要的是调用能力,还是完整源码修改权限?
- 如果只需要调用,是否适合采用 MQH 接口文件配合 EX5 模块?
- 源文件中是否只导出了确实需要开放的函数?
- 是否避免把内部辅助实现无必要地暴露为公共接口?
- 当前 MQH 是否由正确版本的 MQ5 / EX5 模块生成?
- MQH 与 EX5 是否已经作为同一版本成套测试?
- 是否说明了 MQH 和 EX5 应放置的目录位置?
- 如果模块位于 Libraries 目录,是否核对了生成接口与导入路径?
- 是否说明了函数用途、参数含义和返回结果?
- 是否确认不存在遗漏的依赖文件或权限要求?
- 是否保留了自己的完整 MQ5 源码和版本记录?
- 是否明确了试用、项目内调用、转发、修改和再分发边界?
- 是否确认没有传播未经授权的商业源码或第三方代码?
- 是否理解接口共享解决的是调用边界,而不是程序质量或交易结果问题?
十二、总结:把调用能力交出去之前,先把共享边界划清楚
当你开始开发可复用的 MQL5 模块,就会发现合作并不总意味着必须把全部源码发出去。
有时候,对方真正需要的是调用某些功能,而不是查看内部每一步怎样实现。MetaEditor 的 Generate Include File 功能,可以根据 MQ5 文件中明确导出的函数,生成一份 .mqh 接口文件;配合相应的 .ex5 模块,调用方可以在自己的 MQL5 程序中使用这些开放能力。
在这个结构里:MQ5 负责保存和维护实现源码;EX5 负责执行实际功能;MQH 负责描述外部如何调用这些功能。
MQH 更像说明如何连接模块的接口,EX5 才承担实际执行的部分。合作方需要的是调用能力,不一定意味着你要把每一行实现细节都交出去。源码保护不是不合作,而是先把共享范围讲清楚。
不过,接口与实现分离并不能代替授权确认、版本管理和源码备份。分享文件之前,仍要确认自己是否拥有交付权限,MQH 与 EX5 是否版本一致,依赖是否齐全,以及对方究竟被允许怎样使用这些文件。
本文仅作 MetaEditor MQH、MQL5 Include 文件、MT5 函数共享与源码边界说明,不讨论反编译、破解或绕过 EX5 保护的方法,不指导传播未经授权的商业代码,也不提供任何交易策略实现或投资建议。
FAQ:MetaEditor MQH 接口文件常见问题
-
1. MQH 文件是什么?
MQH 是 MQL5 中常见的 Include 文件。它可以保存公共声明、类型或可复用内容。在模块共享场景中,自动生成的 MQH 可以用来描述 EX5 模块对外开放的函数接口。
-
2. MetaEditor Generate Include File 是做什么的?
它可以从当前打开的 MQ5 文件中识别被标记为导出的函数,并生成包含 #import 和函数声明的 MQH 接口文件,方便其他程序调用相应 EX5 模块。
-
3. 哪些函数会被生成到 MQH 接口文件中?
只有在源文件中明确使用 export 标记、准备向外提供调用能力的函数,才会被识别并写入生成的接口文件。内部普通函数不会因为存在于源码中就自动公开。
-
4. MQH 文件可以单独运行模块功能吗?
不能。MQH 主要描述怎样调用函数,真正执行逻辑的是与之对应的 EX5 模块。使用方通常需要同时获得正确版本的 MQH 和 EX5 文件。
-
5. MQ5、MQH 和 EX5 有什么区别?
MQ5 通常是主源码文件,保存具体实现;MQH 通常承担接口或公共声明作用;EX5 是编译后的可执行文件,用于在 MT5 中运行实际功能。
-
6. 如果 MQ5 文件位于 Libraries 目录,生成的 MQH 会放在哪里?
按照 MetaEditor 的生成规则,如果当前源文件位于 MQL5/Libraries 或其子目录,生成的 MQH 接口文件通常会放入 MQL5/Include 目录,并按 Libraries 下的相对路径生成导入信息。
-
7. 生成 MQH 后可以删除 MQ5 源码吗?
不应该。MQH 和 EX5 都不能替代你的实现源码。后续维护、修复、更新接口和重新编译,都需要妥善保存 MQ5 及相关源文件。
-
8. 只发 MQH 和 EX5,是否就等于不需要说明授权范围?
不是。技术上不直接交付源码,并不代表使用权、转发权、修改权和再分发权自然明确。分享前仍应与合作方确认授权范围。
-
9. EX5 模块更新后,旧 MQH 还能继续使用吗?
不一定。如果导出函数接口发生变化,旧 MQH 可能与新 EX5 不匹配,导致加载错误或运行异常。接口文件与执行模块应按版本成套管理。
-
10. 可以将购买来的商业程序生成接口后再分享给他人吗?
不应这样做,除非你拥有明确的分享与交付授权。生成接口文件或提供 EX5 模块,不会改变原代码或程序的授权归属。
-
11. 这种接口共享方式适合交易策略模块吗?
是否适合取决于你拥有的授权、项目需求和测试安排。无论模块用于哪类功能,接口共享都只是代码协作方式,不能说明程序逻辑可靠,也不能代表任何交易结果。