如何将字符串从C ++ DLL返回到MetaTrader 4代码执行生态系统?

时间:2017-04-10 10:29:12

标签: c++ string dll mql4 metatrader4

我有以下功能

__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将 wchar_t* 返回给MetaTrader4。

我尝试了很多方法来返回正确的值并避免内存泄漏,例如set return type const wchar_t*,使用带有delete[] in的析构函数创建我自己的类。但是所有这些尝试都没有成功:我得到{ {1}}代替'??ello'。只是前一个或两个符号不正确。通过创建'hello',它可以正常工作。但是,我想知道,可能有更好的解决方案吗?

4 个答案:

答案 0 :(得分:1)

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

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

为了使其正常工作,您必须使用相同的内存管理器/分配器来分配和释放字符串的内存。

一种选择是使用像COM分配器这样的通用系统范围的分配器。通过这种方式,您可以使用CoTaskMemAlloc在DLL中分配内存,并且调用者可以使用匹配的CoTaskMemFree释放它。

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

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

请注意,为C风格的字符串分配内存时,必须考虑字符串的 NUL-terminator 的附加插槽(因此,您必须分配{{1} } delete[] s)。

答案 1 :(得分:1)

醇' ASM黑客总是习惯于
#assume nothing ; mql4_string != string

Bingo,headbang显而易见。接收方不假设​​,因为 - MQL4.56789被引入,它将字节块表示为 string ,但是 struct(!)

  

(cit。:)字符串类型的内部表示是一个12字节长的结构:

#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

<登记/>    string 类型用于存储文本字符串。文本字符串是Unicode格式的字符序列,最后为零。

答案 2 :(得分:0)

偶然的,我想到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; } 。所以它在不创建线程的情况下解决了我的问题。

 <xsl:copy>
     <xsl:value-of select="format-number(., '#########0.##')"/>
 </xsl:copy>

答案 3 :(得分:0)

另一种方式(稍微简单一点,但仅在某些情况下):

//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();