Создание собственного расширения MetaTrader (dll) - страница 14

 

Привет, Младен!

Когда я пытаюсь получить значение буфера[0], то получается что-то вроде Buffer: 2147483647

Так что я думаю, что это неправильно... Должно быть значение что-то вроде: 1,23584

так как я сделал тест и установил: buffer = Rates[10].close;

Есть идеи?

Большое спасибо и до свидания, AT

 
at120:
Привет, Младен!

Когда я пытаюсь получить значение буфера[0], получается что-то вроде Buffer: 2147483647

Так что я думаю, что это неправильно... Должно быть значение что-то вроде: 1,23584

так как я сделал тест и установил: buffer = Rates[10].close;

Есть идеи?

Большое спасибо и до свидания, AT

Это значение известно как EMPTY_VALUE.

Со стороны mql проверьте, все ли в порядке с объявлением буфера и присвоением значений. Также проверьте, как вы работаете с элементами буфера (массива) со стороны C++.

 

Привет, Младен!

Я попробовал кое-что в вызове DLL и также с буферами, НО без положительных результатов...

Я пытался установить значение буфера в коде C++ равным 1, buffer[]=1; Без изменений...

Я приложил DLL (пожалуйста, просто переименуйте ее из .zip в .dll), которую я вызываю с помощью следующего кода MQL4.

Спасибо за любой вклад/подсказки...

Пока, 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);

}
Файлы:
 
at120:
Привет, Младен!

Я попробовал кое-что в вызове DLL и также с буферами, НО без положительных результатов...

Я пытался установить значение буфера в коде C++ равным 1, buffer[]=1; Без изменений...

Я приложил DLL (пожалуйста, просто переименуйте ее из .zip в .dll), которую я вызываю с помощью следующего кода MQL4.

Спасибо за любой вклад/подсказки...

Пока, 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);

}

Вы не можете использовать buffer[]=1; - это ничего не значит в mql. Вы должны использовать какой-то индекс в части buffer[] (например, buffer[0]=1; ).

 

Привет, Младен!

Я использовал следующее для этого в C++

buffer = 1;

Так что это должно нормально работать...

Код на C++ выглядит как показано ниже.

Спасибо за помощь!!!

Пока, 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

 

У меня проблема с dll на c++, которую я создал для подключения к серверу, отправки команд и закрытия. Я использую библиотеки boost asio C++ и взял пример с их сайта. Я протестировал код как отдельный исполняемый файл в консоли, и он отлично работает, но когда я преобразовал его в dll, то увидел странную проблему с усечением строки.

Только первый символ в строке передается на сервер. Сейчас я отправляю тестовую строку "get time\n", но при получении сообщения отображается только "g".

API выглядит следующим образом (полная версия функции приведена ниже):

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

Я читал, что строка в MQL на самом деле является структурой, и я попробовал использовать предложенную структуру MqlStr, ........

struct MqlStr

{

int len;

char *string;

};

......, но это, похоже, тоже не работает. Сервер зависает, выдавая недопустимую строку.

До сих пор лучше всего работало то, что я перечислил ниже.

Ниже приведено мое тестовое ea, которое не делает ничего, кроме отправки одной и той же строки на сервер каждый тик.

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

#property version "1.00"

#property strict

#import "Boost.dll";

int messageOrder(string message, int length);

#import

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

//| Функция инициализации эксперта |

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

int OnInit()

{

//---

//---

return(INIT_SUCCEEDED);

}

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

//| Функция деинициализации эксперта | |

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

void OnDeinit(const int reason)

{

//---

}

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

//| Функция экспертного тика |

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

void OnTick()

{

//---

string message = "получить время\n";

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

messageOrder(message, StringLen(message));

}

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

Ниже приведен экспорт dll. Я создаю строку std::string после получения сообщения и затем отправляю эту строку на сервер. Проблема заключается в преобразовании строки MQL в C++ char *.

Очевидно, я делаю что-то не так. Может ли кто-нибудь помочь с этим?

extern "C"

{

#define MT4_EXPFUNC __declspec(dllexport)

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

{

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

std::string line = 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 << "Исключение: " << e.what() << "\n";

}

return 0;

}

}

 
revivalfx:
У меня возникла проблема с c++ dll, которую я создал для подключения к серверу, отправки команд и закрытия. Я использую библиотеки boost asio C++ и взял пример с их сайта. Я протестировал код как отдельный исполняемый файл в консоли, и он отлично работает, но когда я преобразовал его в dll, вот где я вижу странную проблему с усечением строк.

Только первый символ в строке передается на сервер. В настоящее время я отправляю тестовую строку "get time\n", но при получении сообщения отображается только "g".

API выглядит следующим образом (полная версия функции приведена ниже):

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

Я читал, что строка в MQL на самом деле является структурой, и я попробовал использовать предложенную структуру MqlStr, ........

struct MqlStr

{

int len;

char *string;

};

......, но это, похоже, тоже не работает. Сервер зависает, выдавая недопустимую строку.

До сих пор лучше всего работало то, что я перечислил ниже.

Ниже приведено мое тестовое ea, которое не делает ничего, кроме отправки одной и той же строки на сервер каждый тик.

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

#property version "1.00"

#property strict

#import "Boost.dll";

int messageOrder(string message, int length);

#import

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

//| Функция инициализации эксперта |

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

int OnInit()

{

//---

//---

return(INIT_SUCCEEDED);

}

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

//| Функция деинициализации эксперта | |

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

void OnDeinit(const int reason)

{

//---

}

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

//| Функция экспертного тика |

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

void OnTick()

{

//---

string message = "получить время\n";

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

messageOrder(message, StringLen(message));

}

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

Экспорт dll приведен ниже. Я создаю строку std::string после получения сообщения и затем отправляю эту строку на сервер. Проблема заключается в преобразовании строки MQL в C++ char *.

Очевидно, я делаю что-то не так. Может ли кто-нибудь помочь с этим?

extern "C"

{

#define MT4_EXPFUNC __declspec(dllexport)

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

{

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

std::string line = 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 << "Исключение: " << e.what() << "\n";

}

return 0;

}

}

Как оказалось, когда я использовал структуру MqlStr, я неправильно ее распаковывал.

Теперь я так и делаю:

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

}

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

Теперь я изучаю C# DLL вместо этого, основываясь на ссылке в предыдущем сообщении.

 

дерьмо! Наверное, я мог посмотреть пример в разделе скриптов. не обращайте внимания. Спасибо...... А! Юникод.

 
revivalfx:
Черт! Думаю, я мог бы посмотреть пример в разделе скриптов. не обращайте внимания. Спасибо...... А! Юникод.

Разве это не длина сообщения?

 

Привет, revalfx,

Вы хотите использовать wchar_t вместо char! У меня была такая же проблема! ;-)

Пока, AT

Причина обращения: