MetaTrader + C++:DLL
MetaTrader 可以调用从 Windows DLL 导出的函数。当 Expert Advisor 或指标需要更易于用 C 或 C++ 维护的代码、需要访问原生库,或者需要比纯脚本实现更好的性能时,这会很有用。
要点很简单:
- 从 DLL 导出普通的 C 风格函数。
- 使用 MetaTrader 期望的正确调用约定。
- 让 MQL 参数类型与原生函数签名匹配。
- 在运行脚本、指标或 Expert Advisor 之前,在 MetaTrader 中启用 DLL 导入。
C++ DLL 示例
一个最小的 C++ DLL 可以像这样暴露函数:
// mt_example.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b)
{
return a + b;
}
extern "C" __declspec(dllexport) double __stdcall Multiply(double a, double b)
{
return a * b;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved)
{
return TRUE;
}
extern "C" 会防止 C++ 名称修饰,因此 MetaTrader 可以按名称找到导出的函数。__declspec(dllexport) 使函数在 DLL 外部可见。__stdcall 通常用于由 MQL 导入的函数。
构建 DLL 时要使用与 MetaTrader 终端相同的架构。32 位终端需要 32 位 DLL,64 位终端需要 64 位 DLL。
MQL 导入示例
编译 DLL 后,将它放在 MetaTrader 可以加载的位置,通常是终端的 MQL4/Libraries 或 MQL5/Libraries 目录。
对于 MQL4:
#import "mt_example.dll"
int Add(int a, int b);
double Multiply(double a, double b);
#import
void OnStart()
{
int sum = Add(2, 3);
double product = Multiply(1.5, 4.0);
Print("sum = ", sum);
Print("product = ", product);
}
对于 MQL5,同样的思路也适用:
#import "mt_example.dll"
int Add(int a, int b);
double Multiply(double a, double b);
#import
void OnStart()
{
int sum = Add(2, 3);
double product = Multiply(1.5, 4.0);
Print("sum = ", sum);
Print("product = ", product);
}
常见检查项
如果 MetaTrader 无法调用 DLL,请先检查这些项目:
- 已在终端以及脚本、指标或 Expert Advisor 设置中启用 DLL 导入。
- DLL 位于正确的
Libraries目录中。 - DLL 架构与终端架构匹配。
- 导出的函数名没有被修饰。使用
dumpbin /exports mt_example.dll或 Dependency Walker 等工具检查导出项。 - MQL 声明与 C++ 函数签名完全匹配。
关于字符串和数组的说明
int 和 double 等基本值最容易传递。字符串、数组和结构体需要更谨慎,因为内存所有权和布局必须与 MetaTrader 的预期一致。
传递字符串时,建议先使用一个小型测试函数,并在将其用于交易代码之前验证编码和缓冲区大小。传递数组时,要同时传入类似指针的参数和长度,并且绝不要假设 DLL 可以安全读取超出给定大小的内容。
实用规则
保持 DLL 接口小而稳定。让 MQL 处理交易逻辑和 MetaTrader 特定状态,而让 C++ DLL 处理隔离的原生工作,例如计算、与另一个原生库集成,或对性能敏感的处理。
