MT4代码如下
#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";
// 转换字符串为 UTF-8 编码
char urlUtf8[];
char headersUtf8[];
char bodyUtf8[];
StringToCharArray(url, urlUtf8, 0, WHOLE_ARRAY, CP_UTF8); // URL 转换为 UTF-8
StringToCharArray(headers, headersUtf8, 0, WHOLE_ARRAY, CP_UTF8); // 请求头转换为 UTF-8
StringToCharArray(jsonData, bodyUtf8, 0, WHOLE_ARRAY, CP_UTF8); // JSON 数据转换为 UTF-8
// 响应数据
char response[8192];
int responseSize = ArraySize(response);
// 调用 DLL 中的 HttpPost 函数
int result = HttpPost(urlUtf8, headersUtf8, bodyUtf8, response, responseSize);
// 处理返回结果
if (result == 0) { // 假设 0 表示请求成功
string responseText = CharArrayToString(response);
Print("请求成功,服务器返回:", responseText);
} else {
PrintFormat("请求失败!错误代码:%d", result);
}
}
C++编写的DLL源代码如下:
#include <windows.h>
#include <string>
#include <sstream>
#include <iostream>
#include <wininet.h>
// 自定义 UTF-8 转 UTF-16
std::wstring ConvertToWideString(const char* utf8String) {
if (!utf8String) return L"";
int wideLength = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0);
std::wstring wideString(wideLength, 0);
MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, &wideString[0], wideLength);
return wideString;
}
// 自定义 UTF-16 转 UTF-8
std::string ConvertToUTF8(const wchar_t* wideString) {
if (!wideString) return "";
int utf8Length = WideCharToMultiByte(CP_UTF8, 0, wideString, -1, NULL, 0, NULL, NULL);
std::string utf8String(utf8Length, 0);
WideCharToMultiByte(CP_UTF8, 0, wideString, -1, &utf8String[0], utf8Length, NULL, NULL);
return utf8String;
}
// 将整数转换为宽字符串
std::wstring ToWString(size_t value) {
std::wstringstream wss;
wss << value;
return wss.str();
}
// 使用 Windows API 写入日志
void WriteLog(const std::string& message) {
const wchar_t* logFileName = L"chriszhao_Debug.log";
HANDLE hFile = CreateFileW(
logFileName,
FILE_APPEND_DATA,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to open log file: " << ConvertToUTF8(logFileName) << std::endl;
return;
}
DWORD bytesWritten = 0;
WriteFile(hFile, message.c_str(), message.size(), &bytesWritten, NULL);
WriteFile(hFile, "\n", 1, &bytesWritten, NULL);
CloseHandle(hFile);
}
// 导出函数声明
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;
}
// 转换 URL 和 Headers 为宽字符
std::wstring wideUrl = ConvertToWideString(url);
std::wstring wideHeaders = ConvertToWideString(headers);
std::string utf8Body = body; // Body 应该是 UTF-8 格式,不需要转换
if (wideUrl.find(L"http://") != 0 && wideUrl.find(L"https://") != 0) {
WriteLog("Error: URL must start with http:// or https://");
return -1;
}
// 打开 Internet 会话
HINTERNET hInternet = InternetOpenW(L"MT4_HTTP_Client", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet) {
WriteLog("Error: InternetOpenW failed! Error code: " + std::to_string(GetLastError()));
return -1;
}
// 解析 URL
URL_COMPONENTSW urlComponents = {0};
wchar_t scheme[16] = {0};
wchar_t hostName[256] = {0};
wchar_t urlPath[1024] = {0};
wchar_t extraInfo[256] = {0};
urlComponents.dwStructSize = sizeof(urlComponents);
urlComponents.lpszScheme = scheme;
urlComponents.dwSchemeLength = sizeof(scheme) / sizeof(wchar_t);
urlComponents.lpszHostName = hostName;
urlComponents.dwHostNameLength = sizeof(hostName) / sizeof(wchar_t);
urlComponents.lpszUrlPath = urlPath;
urlComponents.dwUrlPathLength = sizeof(urlPath) / sizeof(wchar_t);
urlComponents.lpszExtraInfo = extraInfo;
urlComponents.dwExtraInfoLength = sizeof(extraInfo) / sizeof(wchar_t);
if (!InternetCrackUrlW(wideUrl.c_str(), 0, 0, &urlComponents)) {
WriteLog("Error: InternetCrackUrlW failed! URL: " + ConvertToUTF8(wideUrl.c_str()) + ", Error code: " + std::to_string(GetLastError()));
InternetCloseHandle(hInternet);
return -2;
}
WriteLog("InternetCrackUrlW succeeded!");
WriteLog("Scheme: " + ConvertToUTF8(urlComponents.lpszScheme ? urlComponents.lpszScheme : L"NULL"));
WriteLog("HostName: " + ConvertToUTF8(urlComponents.lpszHostName ? urlComponents.lpszHostName : L"NULL"));
WriteLog("UrlPath: " + ConvertToUTF8(urlComponents.lpszUrlPath ? urlComponents.lpszUrlPath : L"NULL"));
WriteLog("Port: " + std::to_string(urlComponents.nPort));
// 创建连接
HINTERNET hConnect = InternetConnectW(hInternet, urlComponents.lpszHostName, urlComponents.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnect) {
WriteLog("Error: InternetConnectW failed! Error code: " + std::to_string(GetLastError()));
InternetCloseHandle(hInternet);
return -3;
}
// 打开 POST 请求
HINTERNET hRequest = HttpOpenRequestW(hConnect, L"POST", urlComponents.lpszUrlPath, NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
if (!hRequest) {
WriteLog("Error: HttpOpenRequestW failed! Error code: " + std::to_string(GetLastError()));
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return -4;
}
// 构造请求头
std::wstring fixedHeaders = L"Content-Type: application/json\r\n";
fixedHeaders += L"Host: 127.0.0.1\r\n";
fixedHeaders += L"Accept: application/json\r\n";
fixedHeaders += L"User-Agent: MT4_HTTP_Client\r\n";
fixedHeaders += L"Content-Length: " + ToWString(utf8Body.size()) + L"\r\n\r\n"; // 额外的空行表示请求头结束
WriteLog("Final Headers (Wide): " + ConvertToUTF8(fixedHeaders.c_str()));
WriteLog("Request Body: " + utf8Body);
// 发送请求
BOOL result = HttpSendRequestW(hRequest, fixedHeaders.c_str(), fixedHeaders.size(), (LPVOID)utf8Body.c_str(), utf8Body.size());
if (!result) {
DWORD errorCode = GetLastError();
WriteLog("Error: HttpSendRequestW failed! Error code: " + std::to_string(errorCode));
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return -5;
}
// 读取响应
char buffer[8192] = {0};
DWORD bytesRead = 0;
result = InternetReadFile(hRequest, buffer, sizeof(buffer) - 1, &bytesRead);
if (!result) {
WriteLog("Error: InternetReadFile failed! Error code: " + std::to_string(GetLastError()));
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return -6;
}
buffer[bytesRead] = '\0';
// 将响应写入输出缓冲区
strncpy(response, buffer, responseSize - 1);
response[responseSize - 1] = '\0';
WriteLog("Response: " + std::string(buffer));
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return 0;
}
编译命令如下:
g++ -std=c++11 -shared -o HttpPost.dll HttpPost.cpp -lwininet












网友评论