Créez votre propre extension MetaTrader (dll) - page 14

 

Bonjour Mladen !

Lorsque j'essaie d'obtenir la valeur de la mémoire tampon[0], la valeur est quelque chose comme Buffer : 2147483647

Je pense donc que ce n'est pas correct... Il devrait y avoir une valeur quelque chose comme : 1,23584

comme j'ai fait un test et mis : buffer = Rates[10].close ;

Des idées ?

Merci beaucoup et au revoir, AT

 
at120:
Bonjour Mladen !

Lorsque j'essaie d'obtenir la valeur de la mémoire tampon[0], la valeur est quelque chose comme Buffer : 2147483647

Je pense donc que ce n'est pas correct... Il devrait y avoir une valeur quelque chose comme : 1,23584

comme j'ai fait un test et défini : buffer = Rates[10].close ;

Des idées ?

Merci beaucoup et au revoir, AT

Cette valeur est ce que l'on appelle EMPTY_VALUE.

Du côté mql, vérifiez si tout va bien avec votre déclaration de tampon et l'affectation des valeurs. Vérifiez également comment vous gérez les éléments du tampon (tableau) du côté C++.

 

Salut Mladen !

J'ai essayé quelque chose en appelant la DLL et aussi avec les tampons, MAIS sans aucun résultat positif...

J'ai essayé de mettre la valeur du buffer dans le code C++ à 1, buffer[]=1 ; Pas de changement...

J'ai joint la DLL (veuillez la renommer de .zip à .dll), que j'appelle avec le code MQL4 suivant

Merci pour toute information ou conseil...

Au revoir, AT

sma_rec.dll.zip

#property indicator_separate_window

#property indicator_buffers 1 // one indicator line to be plotted

#property indicator_color1 Red // plot colour is red - change via GUI

#import "sma_rec.dll"

void updateBuffer(MqlRates &rates[], double& buffer[], int bars, int indicator_counted, int period, double& internal_calcs[2] );

#import

extern int ma_period = 10; // default period is 10 - change via GUI

extern int ma_shift = 0; // default is no shift - change via GUI

double buffer[]; // the indicator buffer - the DLL will // write to this and it will be plotted

MqlRates Rates[];

double internal_calcs[2];

int init(){

// set up the indicator buffer

IndicatorBuffers(2);

SetIndexStyle(0, DRAW_LINE);

SetIndexShift(0, ma_shift);

SetIndexBuffer(0, buffer);

SetIndexLabel(0, "Recursive SMA");

IndicatorDigits(Digits);

return(0);

}

int start(){

ArrayCopyRates(Rates);

updateBuffer( Rates, buffer, Bars, IndicatorCounted(), ma_period, internal_calcs );

// Print("4 - close: ",Rates[0].close,"\n");

//Print("Buffer: ",buffer[0],"\n");

return(0);

}
Dossiers :
 
at120:
Bonjour Mladen !

J'ai essayé quelque chose en appelant la DLL et aussi avec les tampons, MAIS sans aucun résultat positif...

J'ai essayé de mettre la valeur du buffer dans le code C++ à 1, buffer[]=1 ; Pas de changement...

J'ai joint la DLL (veuillez la renommer de .zip à .dll), que j'appelle avec le code MQL4 suivant

Merci pour toute information ou conseil...

Au revoir, AT

sma_rec.dll.zip

#property indicator_separate_window

#property indicator_buffers 1 // one indicator line to be plotted

#property indicator_color1 Red // plot colour is red - change via GUI

#import "sma_rec.dll"

void updateBuffer(MqlRates &rates[], double& buffer[], int bars, int indicator_counted, int period, double& internal_calcs[2] );

#import

extern int ma_period = 10; // default period is 10 - change via GUI

extern int ma_shift = 0; // default is no shift - change via GUI

double buffer[]; // the indicator buffer - the DLL will // write to this and it will be plotted

MqlRates Rates[];

double internal_calcs[2];

int init(){

// set up the indicator buffer

IndicatorBuffers(2);

SetIndexStyle(0, DRAW_LINE);

SetIndexShift(0, ma_shift);

SetIndexBuffer(0, buffer);

SetIndexLabel(0, "Recursive SMA");

IndicatorDigits(Digits);

return(0);

}

int start(){

ArrayCopyRates(Rates);

updateBuffer( Rates, buffer, Bars, IndicatorCounted(), ma_period, internal_calcs );

// Print("4 - close: ",Rates[0].close,"\n");

//Print("Buffer: ",buffer[0],"\n");

return(0);

}

Vous ne pouvez pas utiliser buffer[]=1 ; - cela ne signifie rien en MQL. Vous devez utiliser un index dans la partie buffer[] (comme buffer[0]=1 ; ).

 

Salut Mladen !

J'ai utilisé ce qui suit pour cela en C++

buffer = 1 ;

Donc cela devrait normalement fonctionner...

Le code C++ ressemble à ce qui suit.

Merci pour votre aide !

Au revoir, AT

#include

#include "stdafx.h"

#include

#define WIN32_LEAN_AND_MEAN

#define MT4_EXPFUNC __declspec(dllexport)

//+------------------------------------------------------------------+

//| MT4 HISTORY DATA STRUCT |

//+------------------------------------------------------------------+

#pragma pack(push,1)

struct RateInfo

{

__int64 ctm;

double open;

double low;

double high;

double close;

unsigned __int64 vol_tick;

int spread;

unsigned __int64 vol_real;

};

#pragma pack(pop)

struct MqlStr

{

int len;

char *string;

};

MT4_EXPFUNC void __stdcall updateBuffer(const RateInfo* Rates, double buffer[],int Bars, int IndicatorCounted, int ma_period, double internal_calcs[2] )

{

//---

if(Rates==NULL)

{

printf("updateBuffer: NULL array\n");

}

//---

if(Rates != NULL)

{

printf("updateBuffer: something is in array\n");

}

//---

if(buffer==NULL)

{

printf("updateBuffer: NULL array\n");

}

//---

if(Bars<0)

{

printf("updateBuffer: wrong Bars number (%d)\n", Bars);

}

//---

if(ma_period<0)

{

printf("updateBuffer: wrong MA Period (%d)\n", ma_period);

}

//---

if(ma_period==10)

{

printf("updateBuffer: 10 MA Period (%d)\n", ma_period);

}

// buffer = 1;

//buffer = ( buffer - internal_calcs[0] ) + ( Rates.close/ma_period ); // calculate new SMA value//

// check if the DLL is being called for the very first time

if ( IndicatorCounted == 0 )

{

buffer[0] = Rates[0].close;

buffer[1] = ( Rates[0].close + Rates[1].close ) / 2.0;

for( int ii = 2 ; ii < ma_period ; ii++ )

{

buffer = ( ( buffer * ii ) / (ii+1) ) + ( Rates.close/(ii+1) );

}

for( int ii = ma_period ; ii < Bars - 1 ; ii++ )

{

buffer = ( buffer - (Rates.close/ma_period) ) + ( Rates.close/ma_period );

}

internal_calcs[0] = (Rates.close/ma_period);

internal_calcs[1] = Bars - 1; // how many indicator values calculated so far

}

if ( IndicatorCounted > 0 && (Bars - 1) > internal_calcs[1] ) // evaluates to TRUE if there is a new bar

{

buffer = ( buffer - internal_calcs[0] ) + ( Rates.close/ma_period ); // calculate new SMA value

internal_calcs[0] = (Rates.close/ma_period); // update // internal_calcs with new value for next SMA calc.

internal_calcs[1] = Bars - 1; // update how many indicator values calculated so far

} // end of ( IndicatorCounted > 0 && (Bars - 1) > internal_calcs[1]) if // statement

} // end of main function call

 

J'ai un problème avec une dll c++ que j'ai créée pour se connecter à un serveur, envoyer des commandes et se fermer. J'utilise les bibliothèques C++ de Boost Asio et j'ai pris un exemple sur leur site Web. J'ai testé le code en tant qu'exécutable autonome dans la console et il fonctionne parfaitement, mais lorsque je l'ai converti en dll, j'ai constaté un étrange problème de troncature de chaîne.

Seul le premier caractère de la chaîne semble être transmis au serveur. Actuellement, j'envoie une chaîne de test "get time\n" mais seul "g" est vu lorsque le message est reçu.

L'API ressemble à ceci (la fonction complète est ci-dessous) :

MT4_EXPFUNC int __stdcall messageOrder(char* message, int length)

J'ai lu que la chaîne de caractères dans MQL est en fait une structure et j'ai essayé la structure MqlStr qui a été suggérée, ........

struct MqlStr

{

int len ;

char *string ;

} ;

...... mais cela ne semble pas fonctionner non plus. Elle bloque le serveur avec une chaîne invalide.

Ce qui a le mieux fonctionné jusqu'à présent est ce que j'ai listé ci-dessous.

Voici mon ea de test qui ne fait rien d'autre qu'envoyer la même chaîne au serveur à chaque tick.

---------------

#property version "1.00"

#property strict

#import "Boost.dll" ;

int messageOrder(string message, int length) ;

#import

//+------------------------------------------------------------------+

//| Fonction d'initialisation de l'expert

//+------------------------------------------------------------------+

int OnInit()

{

//---

//---

return(INIT_SUCCEEDED) ;

}

//+------------------------------------------------------------------+

//| Fonction de désinitialisation experte |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

//---

}

//+------------------------------------------------------------------+

//| Fonction tick expert |

//+------------------------------------------------------------------+

void OnTick()

{

//---

string message = "get time\n" ;

//Print("message : ", message, " length = ", StringLen(message)) ;

messageOrder(message, StringLen(message)) ;

}

//+------------------------------------------------------------------+

L'exportation de la dll est ci-dessous. Je crée une std::string après la réception du message, puis j'envoie cette chaîne au serveur. Le problème qui se pose est la conversion de la chaîne MQL en char * C++.

Je fais manifestement quelque chose de mal. Quelqu'un peut-il m'aider ?

extern "C"

{

#define MT4_EXPFUNC __declspec(dllexport)

MT4_EXPFUNC int __stdcall messageOrder(char* message, int length)

{

essai

{

boost::asio::io_service io_service ;

tcp::resolver r(io_service) ;

client c(io_service) ;

//char * p ;

//char msg[1024] ;

//int i ;

//for(i = 0, p= message ; i < longueur ; i++, p++)

//{

// msg = *p ;

//}

//std::string ligne = std::string(msg) ;

std::string ligne = message ;

c.assignMessage(line) ;

c.start(r.resolve(tcp::resolver::query("127.0.0.1", "100"))) ;

io_service.run() ;

}

catch (std::exception& e)

{

std::cerr << "Exception : " << e.what() << "\n" ;

}

return 0 ;

}

}

 
revivalfx:
J'ai un problème avec une DLL C++ que j'ai créée pour se connecter à un serveur, envoyer des commandes et se fermer. J'utilise les bibliothèques C++ de Boost Asio et j'ai pris un exemple sur leur site Web. J'ai testé le code en tant qu'exécutable autonome dans la console et il fonctionne parfaitement, mais lorsque je l'ai converti en dll, c'est là que j'ai constaté un problème bizarre de troncature de chaîne.

Seul le premier caractère de la chaîne semble être transmis au serveur. Actuellement, j'envoie une chaîne de test "get time\n", mais seul "g" est visible lorsque le message est reçu.

L'API ressemble à ceci (la fonction complète est ci-dessous) :

MT4_EXPFUNC int __stdcall messageOrder(char* message, int length)

J'ai lu que la chaîne de caractères dans MQL est en fait une structure et j'ai essayé la structure MqlStr qui a été suggérée, ........

struct MqlStr

{

int len ;

char *string ;

} ;

...... mais cela ne semble pas fonctionner non plus. Elle bloque le serveur avec une chaîne invalide.

Ce qui a le mieux fonctionné jusqu'à présent est ce que j'ai listé ci-dessous.

Voici mon ea de test qui ne fait rien d'autre qu'envoyer la même chaîne au serveur à chaque tick.

---------------

#property version "1.00"

#property strict

#import "Boost.dll" ;

int messageOrder(string message, int length) ;

#import

//+------------------------------------------------------------------+

//| Fonction d'initialisation de l'expert

//+------------------------------------------------------------------+

int OnInit()

{

//---

//---

return(INIT_SUCCEEDED) ;

}

//+------------------------------------------------------------------+

//| Fonction de désinitialisation experte |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

//---

}

//+------------------------------------------------------------------+

//| Fonction tick expert |

//+------------------------------------------------------------------+

void OnTick()

{

//---

string message = "get time\n" ;

//Print("message : ", message, " length = ", StringLen(message)) ;

messageOrder(message, StringLen(message)) ;

}

//+------------------------------------------------------------------+

L'exportation de la dll est ci-dessous. Je crée une std::string après la réception du message, puis j'envoie cette chaîne au serveur. Le problème qui se pose est la conversion de la chaîne MQL en char * C++.

Je fais manifestement quelque chose de mal. Quelqu'un peut-il m'aider ?

extern "C"

{

#define MT4_EXPFUNC __declspec(dllexport)

MT4_EXPFUNC int __stdcall messageOrder(char* message, int length)

{

essai

{

boost::asio::io_service io_service ;

tcp::resolver r(io_service) ;

client c(io_service) ;

//char * p ;

//char msg[1024] ;

//int i ;

//for(i = 0, p= message ; i < longueur ; i++, p++)

//{

// msg = *p ;

//}

//std::string ligne = std::string(msg) ;

std::string ligne = message ;

c.assignMessage(line) ;

c.start(r.resolve(tcp::resolver::query("127.0.0.1", "100"))) ;

io_service.run() ;

}

catch (std::exception& e)

{

std::cerr << "Exception : " << e.what() << "\n" ;

}

return 0 ;

}

}

Il s'avère que lorsque j'utilisais la struct MqlStr, je la déballais de manière incorrecte.

C'est ce que je fais maintenant :

struct MqlStr

{

int len;

char *string;

};

extern "C"

{

#define MT4_EXPFUNC __declspec(dllexport)

MT4_EXPFUNC int __stdcall messageOrder(MqlStr * message, int length)

/// MT4_EXPFUNC int __stdcall messageOrder(char* message, int length)

{

std::string line;

try

{

boost::asio::io_service io_service;

tcp::resolver r(io_service);

client c(io_service);

//char * p;

//char msg[1024];

//int i;

//for(i = 0, p= message; i < length; i++, p++)

//{

// msg = *p;

//}

//std::string line = std::string(msg);

line = message[0].string;

c.assignMessage(line);

c.start(r.resolve(tcp::resolver::query("127.0.0.1", "100")));

io_service.run();

}

catch (std::exception& e)

{

std::cerr << "Exception: " << e.what() << "\n";

}

//return line.length();

return strlen(message[0].string);

//return message[0].len;

}

}

[/CODE]

I return the length of the MqlStr string and it is always 1. So it is doing exactly the same as the implementation above.

Here's the MQL code.

[CODE]

#property version "1.00"

#property strict

#import "Boost.dll";

int messageOrder(string message, int length);

#import

//+------------------------------------------------------------------+

//| Expert initialization function |

//+------------------------------------------------------------------+

int OnInit()

{

//---

//---

return(INIT_SUCCEEDED);

}

//+------------------------------------------------------------------+

//| Expert deinitialization function |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

//---

}

//+------------------------------------------------------------------+

//| Expert tick function |

//+------------------------------------------------------------------+

void OnTick()

{

//--- int len = 0;

string message = "get time\n";

//Print("message: ", message, " length = ", StringLen(message));

len = messageOrder(message, StringLen(message)); Print("len ", len);

}

//+------------------------------------------------------------------+

J'explore maintenant une DLL C# à la place en me basant sur un lien dans un post précédent.

 

derp ! Je suppose que j'aurais pu regarder l'exemple sous les scripts. Je n'en tiens pas compte. Merci...... Ah ! Unicode.

 
revivalfx:
derp ! Je suppose que j'aurais pu regarder l'exemple sous les scripts. Ignorer. Merci...... Ah ! Unicode.

Ce n'était pas la longueur d'un message ?

 

Salut revalfx,

Vous voulez utiliser wchar_t au lieu de char ! J'ai eu le même problème ! ;-)

Bye, AT

Raison: