Обсуждение статьи "Избавляемся от балласта самодельных DLL" - страница 3

 
Dmitri Custurov #:
Интересно, можно ли получить реальный указатель на функцию. Указатели, полученные с помощью typedef, отлично работают внутри mql программы. Но к сожалению передать в dll мне их не удалось.

Если с++ + встроенный ассемблер можешь и в курсе что и как в стек кладется, а термины дальний и ближний вызов понятны, то можешь попробовать. Гарантию, что получится не дам, но по идее можно.

 
Где ошибка?
#import "msvcrt.dll"
  int memcpy( const int &dst, const int src, const int cnt );
  int memcpy( const int &dst[], const int &src[], const int cnt );  
#import

void OnStart()
{
  int Array[];
  ArrayResize(Array, 1);
  Array[0] = 123;

  const int Address = msvcrt::memcpy(Array, Array, 0);
  int Value = 0;
  
  msvcrt::memcpy(Value, Address + 0, sizeof(int)); // Crash.

  Print(Value);
}
 
fxsaber #:
Где ошибка?
#import "msvcrt.dll"
        int memcpy(int &dst, int &src[], int cnt);  
        int memcpy(int &dst[], int &src[], int cnt);  
#import



void OnStart() {
        int Array[];
        ArrayResize(Array, 1);
        Array[0] = 123;
        int Value = 0;
        
        msvcrt::memcpy(Value, Array, sizeof(int));
        Print(Value);   // 123
}
 
Edgar Akhmadeev #:

Ваш пример в коде совсем иной. Я пытаюсь взять значение по адресу.

В статье есть пример.

#import "kernel32.dll"
  int OpenFileMappingW(int dwDesiredAccess, int bInheritHandle,  string lpName);
  int MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, 
                      int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
  int UnmapViewOfFile(int lpBaseAddress);
  int CloseHandle(int hObject);
#import "msvcrt.dll"
  int memcpy(uchar &Destination[], int Source, int Length);
  int memcpy(int Destination, int &Source, int Length);
  int memcpy(int Destination, uchar &Source[], int Length);
#import

#define FILE_MAP_ALL_ACCESS   0x000F001F

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
  //--- открываем объект памяти
  int hmem=OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, "Local\\file");
  //--- получаем указатель на память
  int view=MapViewOfFile(hmem, FILE_MAP_ALL_ACCESS, 0, 0, 0); 
  //--- читаем первые 10 байт из памяти
  uchar src[10];
  memcpy(src, view, 10);
  int num=10;
  //--- записываем в начало памяти 4 байтовое int число
  memcpy(view, num, 4);
  //--- закрываем просмотр
  UnmapViewOfFile(view); 
  //--- закрываем объект
  CloseHandle(hmem); 
}
Выделил места, где идет запись по адресу. Однако, этот пример из статьи тоже вызывает краш.
 
fxsaber #:

Ваш пример в коде совсем иной. Я пытаюсь взять значение по адресу.

В статье есть пример.

Выделил места, где идет запись по адресу. Однако, этот пример из статьи тоже вызывает краш.

Я сразу понял, что Вы хотели. Уверен, что адрес, возвращаемый из WinAPI функций, нельзя использовать в MQL5. А вот в аргументы адрес передаётся верно.

Абсолютно убедиться можно было бы, написав простейшую DLL, которая показывает получаемый в аргументе адрес, и возвращает его. И сравнить в MQL5 результат. Здесь многие практикуют C.

 
fxsaber #:
Где ошибка?
#import "msvcrt.dll"
ulong memcpy(ulong destination,ulong source,ulong count_bytes);
ulong memcpy(ulong destination,uchar &source[],ulong count_bytes);
ulong memcpy(ulong destination,ulong &source[],ulong count_bytes);
ulong memcpy(uchar &destination[],ulong source,ulong count_bytes);
ulong memcpy(ulong &destination[],ulong source,ulong count_bytes);
ulong memcpy(ulong &destination[],ulong source,ulong count_bytes);
#import

Исправил ваше:

#import "msvcrt.dll"
  int memcpy(uchar &Destination[], int &Source, 
ulong Length);
  int memcpy(int &Destination, int &Source, ulong Length);
  int memcpy(int &Destination, uchar &Source[], ulong Length);
#import

У вас везде Lenght должен быть не более 4

Копирование более 2Гб работает

Получение начального адреса массива:

uchar Source[];
ArrayResize(Source,1024*1024*1024);
ulong Source_pointer=memcpy(Source,0,0); 
 
fxsaber #:

Ваш пример в коде совсем иной. Я пытаюсь взять значение по адресу.

В статье есть пример.

Выделил места, где идет запись по адресу. Однако, этот пример из статьи тоже вызывает краш.

конечно вызывает..прототипы от 4-ки (32-х битный адрес а-ля unsigned int), а компилишь/запускаешь в 5-ке (у неё 64)

никому нельзя доверять, используешь WinAPI - пиши прототипы сам. А лучше писать свою DLL, пусть она дёргает winapi, а наверх в mql отдаёт интерфейсы более высокого уровня

 
Aliaksandr Hryshyn #:

Копирование более 2Гб работает

Получение начального адреса массива:

Я момент с 64bit-адресом упустил. Но у меня с исправленным адресом всё равно крашится. Это точно должно работать? Полный пример исправленного кода fxsaber можно?

Пока что я при своём мнении - адрес из WinAPI несовместим с MQL.

 
Aliaksandr Hryshyn #:

Исправил ваше:

Maxim Kuznetsov #:

конечно вызывает..прототипы от 4-ки (32-х битный адрес а-ля unsigned int), а компилишь/запускаешь в 5-ке (у неё 64)

Спасибо, теперь работает.
#import "msvcrt.dll"
  ulong memcpy( const int &dst, const ulong src, const int cnt );
  ulong memcpy( const int &dst[], const int &src[], const int cnt );  
#import

void OnStart()
{
  int Array[];
  ArrayResize(Array, 1);
  Array[0] = 123;

  const ulong Address = msvcrt::memcpy(Array, Array, 0);
  int Value = 0;
  
  msvcrt::memcpy(Value, Address + 0, sizeof(int)); // Crash.

  Print(Value);
}
 
fxsaber #:
Спасибо, теперь работает.

последний параметр (который cnt) тоже 64 бита. Он size_t 

https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/memcpy-wmemcpy

memcpy, wmemcpy
memcpy, wmemcpy
  • TylerMSFT
  • learn.microsoft.com
Learn more about: memcpy, wmemcpy