MQL4 C ++ Dll在函数调用中更改字符串参数

时间:2021-07-06 14:54:31

Here is my code for a MetaTraderWrapper.dll:

这是我的MetaTraderWrapper.dll代码:

#define MT4_EXPFUNC __declspec(dllexport)

MT4_EXPFUNC void __stdcall PopMessageString(wchar_t *message)
{
    auto result = L"Hello world !";
    int  n      = wcslen( result );
    wcscpy_s( message, n + 1, result );
}

On the MQL4-Caller side this Script is used:

在MQL4-Caller端,使用此脚本:

#property strict
#import "MetaTraderWrapper.dll"
     int PopMessageString( string & );
#import
//
void OnStart(){
     string message;
     if (  StringInit( message, 64 ) ){
           PopMessageString(  message );
           int n = StringLen( message );
           MessageBox(        message );
     }
}

In this way it works, when a message have been properly initialized with a StringInit() function and enough memory was allocated.

通过这种方式,当使用StringInit()函数正确初始化消息并分配了足够的内存时,它可以正常工作。

What I need to do is, to allocate the message variable not in MQL4 script, but within the DLL.

我需要做的是,分配消息变量不是在MQL4脚本中,而是在DLL中。

In a c++ function, should be something like this:

在c ++函数中,应该是这样的:

MT4_EXPFUNC void __stdcall PopMessageString(wchar_t *message)
{
    auto result = L"Hello world !";
    int  n      = wcslen( result );

    // allocate here, but does not work
    message = new wchar_t[n + 1];        // <--------- DOES NOT WORK
    //
    wcscpy_s( message, n + 1, result );
}

What can I do ?

我能做什么 ?

1 个解决方案

#1


0  

Get acquainted with Wild Worlds of MQL4:
Step 1: forget a string to be string ( it is a struct ... since 2014 )

Internal representation of the string type is a structure of 12 bytes long:

字符串类型的内部表示是一个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)

So,
having headbanged into this one sunny Sunday afternoon, as the platform undergone a LiveUpdate and suddenly all DLL-call-interfaces using a string stopped work, it took a long way to absorb the costs of such "swift" engineering surprise.

所以,在这个阳光明媚的星期天下午,随着平台经历了一个LiveUpdate,突然所有使用字符串的DLL调用接口停止了工作,它花了很长的时间来吸收这种“快速”工程惊喜的成本。

You can re-use the found solution:

您可以重复使用找到的解决方案:

use an array of bytes - uchar[] and convert appropriately bytes of returned content on MQL4 side into string by service functions StringToCharArray() resp. CharArrayToString()

使用一个字节数组 - uchar []并通过服务函数StringToCharArray()resp将MQL4端返回内容的字节转换为字符串。 CharArrayToString()

The DLL-.mqh-header file may also add these tricks and make these conversions "hidden" from MQL4-code:

DLL-.mqh-header文件也可能添加这些技巧并使这些转换从MQL4代码中“隐藏”:

#import <aDLL-file>                                       // "RAW"-DLL-call-interfaces
...
// Messages:
           int      DLL_message_init(       int &msg[] );
           int      DLL_message_init_size ( int &msg[], int    size );
           int      DLL_message_init_data ( int &msg[], uchar &data[], int size );
           ...
#import

// ------------------------------------------------------ // "SOFT"-wrappers
...
int                MQL4_message_init_data ( int &msg[], string data, int size ) {  uchar dataChar[]; StringToCharArray( data, dataChar );
   return (         DLL_message_init_data (      msg,          dataChar, size ) );
}

Always be pretty carefull with appropriate deallocations, not to cause memory leaks.

始终要非常小心适当的解除分配,不要导致内存泄漏。

Always be pretty cutious when new LiveUpdate changes the code-base and introduces new compiler + new documentation. Re-read whole documentation, as many life-saving details come into the help-file only after some next update and many details are hidden or reflected indirectly in chapters, that do not promise such information on a first look -- so, become as ready as D'Artagnan or red-scarfed pioneer -- you never know, where the next hit comes from :)

当新的LiveUpdate更改代码库并引入新的编译器+新文档时,总是非常有用。重新阅读整个文档,因为许多救生详细信息只有在下一次更新之后才会进入帮助文件,并且许多细节会在章节中间接隐藏或反映出来,这些信息不会在第一眼看到这样的信息 - 因此,变为准备作为D'Artagnan或红色先锋 - 你永远不知道,下一个打击来自哪里:)

#1


0  

Get acquainted with Wild Worlds of MQL4:
Step 1: forget a string to be string ( it is a struct ... since 2014 )

Internal representation of the string type is a structure of 12 bytes long:

字符串类型的内部表示是一个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)

So,
having headbanged into this one sunny Sunday afternoon, as the platform undergone a LiveUpdate and suddenly all DLL-call-interfaces using a string stopped work, it took a long way to absorb the costs of such "swift" engineering surprise.

所以,在这个阳光明媚的星期天下午,随着平台经历了一个LiveUpdate,突然所有使用字符串的DLL调用接口停止了工作,它花了很长的时间来吸收这种“快速”工程惊喜的成本。

You can re-use the found solution:

您可以重复使用找到的解决方案:

use an array of bytes - uchar[] and convert appropriately bytes of returned content on MQL4 side into string by service functions StringToCharArray() resp. CharArrayToString()

使用一个字节数组 - uchar []并通过服务函数StringToCharArray()resp将MQL4端返回内容的字节转换为字符串。 CharArrayToString()

The DLL-.mqh-header file may also add these tricks and make these conversions "hidden" from MQL4-code:

DLL-.mqh-header文件也可能添加这些技巧并使这些转换从MQL4代码中“隐藏”:

#import <aDLL-file>                                       // "RAW"-DLL-call-interfaces
...
// Messages:
           int      DLL_message_init(       int &msg[] );
           int      DLL_message_init_size ( int &msg[], int    size );
           int      DLL_message_init_data ( int &msg[], uchar &data[], int size );
           ...
#import

// ------------------------------------------------------ // "SOFT"-wrappers
...
int                MQL4_message_init_data ( int &msg[], string data, int size ) {  uchar dataChar[]; StringToCharArray( data, dataChar );
   return (         DLL_message_init_data (      msg,          dataChar, size ) );
}

Always be pretty carefull with appropriate deallocations, not to cause memory leaks.

始终要非常小心适当的解除分配,不要导致内存泄漏。

Always be pretty cutious when new LiveUpdate changes the code-base and introduces new compiler + new documentation. Re-read whole documentation, as many life-saving details come into the help-file only after some next update and many details are hidden or reflected indirectly in chapters, that do not promise such information on a first look -- so, become as ready as D'Artagnan or red-scarfed pioneer -- you never know, where the next hit comes from :)

当新的LiveUpdate更改代码库并引入新的编译器+新文档时,总是非常有用。重新阅读整个文档,因为许多救生详细信息只有在下一次更新之后才会进入帮助文件,并且许多细节会在章节中间接隐藏或反映出来,这些信息不会在第一眼看到这样的信息 - 因此,变为准备作为D'Artagnan或红色先锋 - 你永远不知道,下一个打击来自哪里:)