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

 

Опубликована статья Избавляемся от балласта самодельных DLL:

Если MQL5-программисту недостаточно функционала языка, он вынужден обращаться к дополнительным инструментам. Для этого приходится использовать другой язык программирования и создавать промежуточную DLL. В MQL5 имеется механизм представления разных типов данных с помощью структур и передачи их в API, но к сожалению, MQL5 не отвечает нам на вопрос о том, как вытянуть данные из принятого указателя. В данной статье мы поставим точку в этом вопросе и покажем простые механизмы обмена сложными типами данных и работе с ними.

Пример копирования 4 байт при помощи функции memcpy

Автор: Alex Sergeev

 
Спасибо за статью, вопрос: при использовании функции memcpy, в примере мы писали адресс в int, если система х64, использовать long переменную? Как программно выяснить какая система (х64, х86)? Спасибо.
 

по вопросу о long - можно, но это вообще не нужно, если вы используете int именно в качестве 4 байтовго приемника чего то там типа от массива чаров. (то есть передаете именно по указателю &).

как узнать -вот тут может http://forum.ixbt.com/topic.cgi?id=26:37968

 
sergeev:

по вопросу о long - можно, но это вообще не нужно, если вы используете int именно в качестве 4 байтовго приемника чего то там типа от массива чаров. (то есть передаете именно по указателю &).

как узнать -вот тут может http://forum.ixbt.com/topic.cgi?id=26:37968

Что то можете прояснить про Время обмена в данной структуре  ( например для 10 чисел формата Int )?
 
shelandr:
Что то можете прояснить про Время обмена в данной структуре  ( например для 10 чисел формата Int )?

уточните вопрос.

вы спрашиваете про скорострельность memcpy ?  думаю это творческий вопрос относящийся больше к работе виндовой библиотеки а не к mql

 

День добрый. Не смотря на то, что статья была написана относительно давно, вопрос обмена данными с библиотечными dll и по сей день остается актуальным. Я сам недавно столкнулся с необходимостью реализации определенного функционала и у меня встал выбор: писать свою dll или все же попробовать воспользоваться библиотечными. Я сделал выбор в пользу вторых и естественно столкнулся со сложностью передачи структур и получения данных обратно. Прочитав данную статью я не совсем уловил некоторых моментов, которые по моему мнению являются весьма усложненными. В данной статье при передаче структуры во внешнюю среду предлагается использовать массив, как выделенную область памяти, в которую библиотечная функция положит результат, и который нам в дальнейшем необходимо преобразовать для дальнейшей работы. У меня очень мало опыта в этой области и возможно дальнейшие мои рассуждения покажутся дилетантскими, но все же выскажу свое мнение в надежде что умные люди меня поправят. Рассмотрим простой пример, указанный в старой статье https://www.mql5.com/ru/articles/1543

В той статье рассматривается вопрос поиска файлов средствами библиотечных dll. Там так же предлагается передавать указатель на массив нужного размера, а потом из этого массива извлекать нужные данные.

А что такое по сути структура? Это тот же самый участок памяти. Теперь попробуем изменить подход к передаче структур и получения данных:

// Объявляем дефайны типов данных

#define DWORD int
#define TCHAR short // Устанавливаем данный тип, так как будем работать с unicode
#define MAX_PATH (260)

// Объявляем структуру FILETIME
struct FILETIME {
  DWORD dwLowDateTime;
  DWORD dwHighDateTime; 
};

// Объявляем структуру данных результатов поиска
struct _WIN32_FIND_DATA {
  DWORD dwFileAttributes;
  FILETIME ftCreationTime;
  FILETIME ftLastAccessTime;
  FILETIME ftLastWriteTime;
  DWORD nFileSizeHigh;
  DWORD nFileSizeLow;
  DWORD dwReserved0;
  DWORD dwReserved1;
  TCHAR cFileName[MAX_PATH];
  TCHAR cAlternateFileName[14]; 
};

// Объявив типы данных мы копируем структуры WinAPI вообще без изменений
// Импортируем библиотечную функцию
#import "kernel32.dll"
   int  FindFirstFileW(string path, _WIN32_FIND_DATA& answer);
#import 
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
// Создаем переменную с типом ранее созданной структуры    
   _WIN32_FIND_DATA data;
// Обращаемся к библиотечной функции, передавая указатель на нашу структуру, а по сути на выделенную память   
int handle = FindFirstFileW(TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Experts\\*.mq5", data);
   if(handle!=-1)
      {
        // Просматриваем результат поиска, обращаясь к полям нашей структуры без дополнительного преобразования 
Print("Имя найденного файла: ", ShortArrayToString(data.cFileName));   
         Print("Временное имя найденного файла: ", ShortArrayToString(data.cAlternateFileName));
         Print("Размер найденного файла: ", data.nFileSizeLow); 
      }
//---
   return(INIT_SUCCEEDED);
  }
//+-
Групповые файловые операции
Групповые файловые операции
  • 2008.07.15
  • MetaQuotes Software Corp.
  • www.mql5.com
Иногда требуется проделать одинаковые операции для некоторой группы файлов. Если у вас есть список файлов, входящих в эту группу, то это не проблема. Но если этот список нужно получить самостоятельно, то возникает вопрос: "Каким образом?" В статье предлагается сделать это с помощью функций FindFirstFile() и FindNextFile(), входящих в библиотеку kernel32.dll.
 
Алексей Барбашин:ых dll. Там так же предлагается передавать указатель на массив нужного размера, а потом из этого массива извлекать нужные данные.

А что такое по сути структура? Это тот же самый участок памяти. Теперь попробуем изменить подход к передаче структур и получения данных:

Вставил ваш код правильно через редактор

 
Rashid Umarov:

Вставил ваш код правильно через редактор


Спасибо большое! Я пока не разобрался как тут правильно код оформлять. (((

 
Алексей Барбашин:

Спасибо большое! Я пока не разобрался как тут правильно код оформлять. (((


Как вставить код.

 
Vladimir Karputov:

Как вставить код.


Спасибо! Изучу! )))

 

Автору статьи большая благодарность за столь доступное представление информации о возможностях взаимодействия IPC без велосипедных dll.

Работа с памятью мне кажется достаточно сложной, но подход понятен, за исключением некоторых вопросов, надеюсь знающие люди помогут разобраться:

1. При помощи memcpy копируем в массив uchar[2] двухбайтовую переменную short, как информация ложится в сам массив?

В каком формате будут находиться значения по индексу 0 и 1 массива uchar?

uchar dst[2];
short src = 13331;
memcpy(dst, src, sizeof(src));

uchar[0] = ?, uchar[1] = ?;

Значение разбивается побайтно и пишется в массив, ок ... Тут вроде понятно.

Не могу понять какие значения попадают в этот массив и как из них получить исходное, вопрос не стоит в том, что я не могу вывести эти значения на экран.


2.  Как правильно заполнить массив uchar[4] значениями разных типов при копировании memcpy, например:

uchar dst[4];
short src1 = 2;
short src2 = 13331;
memcpy(dst, src1, sizeof(src1));
memcpy(dst, src2, sizeof(src2)); // Перезаписывает уже существующее значение, т.е.,  как я предполагаю, нужно при записи в dst указывать адрес уже со смещением на 2 байта после записи src1.

Чувствуется что ответ тривиален и все делается просто, но как это правильно записать ?