美文网首页
MT4使用DLL文件处理网络请求的示例

MT4使用DLL文件处理网络请求的示例

作者: AI_Finance | 来源:发表于2025-03-06 08:45 被阅读0次

MT4脚本,MT4脚本默认使用unicode,utf-16编码,而目前dll代码用的字符集是ansi,所以下面的代码需要做一次字符集转换

#import "HttpPost.dll"
int HttpPost(char &url[], char &headers[], char &body[], char &response[], int responseSize);
#import

void OnStart()
{
    // 定义测试的 URL
    string url = "http://127.0.0.1:8000/api/ainance/mt/receive_order";
    
    // 定义测试的 JSON 数据
    string jsonData = "{\"symbol\": \"EURUSD\", \"lot_size\": 1.5, \"price\": 1.12345, \"order_type\": \"BUY\"}";
    
    // 定义测试的请求头
    string headers = "Content-Type: application/json\r\n";

    // 转换字符串为 ANSI 编码
    char urlAnsi[];
    char headersAnsi[];
    char bodyAnsi[];
    StringToCharArray(url, urlAnsi);        // URL 转换为 ANSI
    StringToCharArray(headers, headersAnsi); // 请求头转换为 ANSI
    StringToCharArray(jsonData, bodyAnsi);  // JSON 数据转换为 ANSI

    // 响应数据
    char response[8192];
    int responseSize = ArraySize(response);

    // 调用 DLL 中的 HttpPost 函数
    int result = HttpPost(urlAnsi, headersAnsi, bodyAnsi, response, responseSize);

    // 处理返回结果
    if (result == 0)  // 假设 0 表示请求成功
    {
        string responseText = CharArrayToString(response);
        Print("请求成功,服务器返回:", responseText);
    }
    else
    {
        PrintFormat("请求失败!错误代码:%d", result);
    }
}

对应的dll的代码:下面的代码用ansi字符集

#include <windows.h>
#include <string>
#include <iostream>
#include <wininet.h>
#include <fstream>

// 调试日志函数
void WriteLog(const std::string& message) {
    std::string logFileName = "chriszhao_Debug.log";
    std::ofstream logFile(logFileName, std::ios::app);
    if (logFile.is_open()) {
        logFile << message << std::endl;
        logFile.close();
    }
}

// 导出函数声明
extern "C" __declspec(dllexport) int HttpPost(const char* url, const char* headers, const char* body, char* response, int responseSize);

// HTTP POST 函数实现
extern "C" __declspec(dllexport) int HttpPost(const char* url, const char* headers, const char* body, char* response, int responseSize) {
    WriteLog("HttpPost called with parameters:");
    WriteLog("URL: " + std::string(url));
    WriteLog("Headers: " + std::string(headers));
    WriteLog("Body: " + std::string(body));

    if (!url || strlen(url) == 0) {
        WriteLog("Error: URL is empty or null!");
        return -1;
    }

    if (std::string(url).find("http://") != 0 && std::string(url).find("https://") != 0) {
        WriteLog("Error: URL must start with http:// or https://");
        return -1;
    }

    // 打开 Internet 会话
    HINTERNET hInternet = InternetOpen("MT4_HTTP_Client", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hInternet) {
        WriteLog("Error: InternetOpen failed! Error code: " + std::to_string(GetLastError()));
        return -1;
    }

    // 解析 URL
    URL_COMPONENTS urlComponents = {0};
    char scheme[16] = {0};
    char hostName[256] = {0};
    char urlPath[1024] = {0};
    char extraInfo[256] = {0};

    urlComponents.dwStructSize = sizeof(urlComponents);
    urlComponents.lpszScheme = scheme;
    urlComponents.dwSchemeLength = sizeof(scheme);
    urlComponents.lpszHostName = hostName;
    urlComponents.dwHostNameLength = sizeof(hostName);
    urlComponents.lpszUrlPath = urlPath;
    urlComponents.dwUrlPathLength = sizeof(urlPath);
    urlComponents.lpszExtraInfo = extraInfo;
    urlComponents.dwExtraInfoLength = sizeof(extraInfo);

    if (!InternetCrackUrl(url, strlen(url), 0, &urlComponents)) {
        WriteLog("Error: InternetCrackUrl failed! URL: " + std::string(url) + ", Error code: " + std::to_string(GetLastError()));
        InternetCloseHandle(hInternet);
        return -2;
    }

    WriteLog("InternetCrackUrl succeeded!");
    WriteLog("Scheme: " + std::string(urlComponents.lpszScheme ? urlComponents.lpszScheme : "NULL"));
    WriteLog("HostName: " + std::string(urlComponents.lpszHostName ? urlComponents.lpszHostName : "NULL"));
    WriteLog("UrlPath: " + std::string(urlComponents.lpszUrlPath ? urlComponents.lpszUrlPath : "NULL"));
    WriteLog("Port: " + std::to_string(urlComponents.nPort));

    // 创建连接
    HINTERNET hConnect = InternetConnect(hInternet, urlComponents.lpszHostName, urlComponents.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) {
        WriteLog("Error: InternetConnect failed! Error code: " + std::to_string(GetLastError()));
        InternetCloseHandle(hInternet);
        return -3;
    }

    // 打开 POST 请求
    HINTERNET hRequest = HttpOpenRequest(hConnect, "POST", urlComponents.lpszUrlPath, NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
    if (!hRequest) {
        WriteLog("Error: HttpOpenRequest failed! Error code: " + std::to_string(GetLastError()));
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return -4;
    }

    // 发送请求
    BOOL result = HttpSendRequest(hRequest, headers, strlen(headers), (LPVOID)body, strlen(body));
    if (!result) {
        WriteLog("Error: HttpSendRequest failed! Error code: " + std::to_string(GetLastError()));
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return -5;
    }

    // 读取响应
    DWORD bytesRead = 0;
    result = InternetReadFile(hRequest, response, responseSize - 1, &bytesRead);
    if (!result) {
        WriteLog("Error: InternetReadFile failed! Error code: " + std::to_string(GetLastError()));
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return -6;
    }

    response[bytesRead] = '\0';
    WriteLog("Response: " + std::string(response));

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);

    return 0;
}

这个dll文件的编译方式为:
g++ -shared -o HttpPost.dll HttpPost.cpp -lwininet "-Wl,--out-implib,HttpPost.lib”

相关文章

网友评论

      本文标题:MT4使用DLL文件处理网络请求的示例

      本文链接:https://www.haomeiwen.com/subject/mgllmjtx.html