如何 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_t
s).
不小心把心思放到了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();
我有以下功能
__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_t
s).
不小心把心思放到了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
Thestring
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();