如何 return 来自 C++ DLL 的字符串到 MetaTrader 4 代码执行生态系统中?

How to return a string from a C++ DLL into a MetaTrader 4 code-execution ecosystem?

我有以下功能

__declspec(dllexport) wchar_t* __stdcall __getJson(wchar_t * listN){
setlocale(LC_ALL, "");
//function logic
wstring ant = utf8_to_wstring(result);
const WCHAR* constRes = ant.c_str();
WCHAR* tempObj=new WCHAR[ant.length()];
wcscpy(tempObj, constRes);
thread Thread([tempObj]{
    Sleep(1000);
    delete[] tempObj;
});
Thread.detach();
return tempObj;
}

这个 DLL returns wchar_t* 到 MetaTrader4.

我尝试了很多方法来 return 更正值并避免内存泄漏,例如设置 return 类型 const wchar_t*,使用 [=14 的析构函数创建我自己的 class =] 中。但是所有这些尝试都没有成功:我得到的是 '??ello' 而不是 'hello'。只有前一两个符号不正确。通过创建 thread 它可以正常工作。但是,我想知道,是否有更好的解决方案?

要在 DLL 中创建一个字符串并将其传递给调用者,您必须在 DLL 中动态分配一些内存来存储字符串的字符,并将指向该内存的指针传递给调用者。

此外,调用者必须能够在不再需要该字符串时释放该内存。

要使其正常工作,您必须使用相同的内存manager/allocator来分配和释放字符串的内存。

一种选择是使用通用的系统范围分配器,如 COM 分配器。这样就可以使用CoTaskMemAlloc在DLL中分配内存,调用者可以使用匹配的CoTaskMemFree.

释放内存

另一种选择是 return 一个 BSTR 字符串,在 DLL 中用 SysAllocString 分配。调用者将释放该字符串调用 SysFreeString.

或者,您可以提供一个自定义函数来释放 DLL 中字符串的内存。例如,您可以使用 new[] 在 DLL 中分配字符串的内存,并且可以提供调用 delete[].

MyDllFreeString 函数

请注意,当您为 C 风格的字符串分配内存时,您必须考虑为字符串的 NUL 终止符 分配一个额外的插槽(因此,您必须分配 stringLength + 1 wchar_ts).

不小心把心思放到了BOOL APIENTRY DllMain。所以它在不创建线程的情况下解决了我的问题。

vector<wchar_t*> tempObjVector;

BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{
   switch (ul_reason_for_call)
   {
   case DLL_PROCESS_ATTACH:
   case DLL_THREAD_ATTACH:
   case DLL_THREAD_DETACH:
   case DLL_PROCESS_DETACH: 
       while (tempObjVector.size() != 0)
       {
           delete[] tempObjVector.back();
           tempObjVector.pop_back();
       }
       break;
   }
   return TRUE;
}

__declspec(dllexport) wchar_t* __stdcall __getJson(wchar_t * listN){
    ....
    ....
    wchar_t* tempObj=new wchar_t[ant.length()+1];
    tempObj[ant.length()] = 0;
    wcscpy(tempObj, constRes);
    tempObjVector.push_back(tempObj);
    return tempObj;
}

#ol' ASM hackers always used to start with
#assume nothing ; mql4_string != string

宾果游戏,headbang 很明显。接收方不假设​​,因为 New-MQL4.56789 被引入,它表示一个字节块作为 string, 但是 struct (!).

(cit.:) Internal representation of the string type is a structure of 12 bytes long:

#pragma pack(push,1) 
struct MqlString 
       { 
                int      size;       // 32-bit integer, contains size of the buffer, allocated for the string. 
                LPWSTR   buffer;     // 32-bit address of the buffer, containing the string. 
                int      reserved;   // 32-bit integer, reserved. 
                }; 
#pragma pack(pop,1)

(cit.:) ( MQL4-side doc: )
String Type


The string type is used for storing text strings. A text string is a sequence of characters in the Unicode format with the final zero at the end of it.

另一种方法(更简单一些,但仅适用于某些情况):

//C++
extern "C" __declspec(dllimport) const wchar_t *GetMessage();
const wchar_t *GetMessage()
{
    static std::wstring last_message;
    last_message = GetSomeMessage();
    return last_message.c_str();
}

//MQL
#import "MyDll.dll"
string GetMessage();
#import
string message = GetMessage();