Экспорт функций и переменных из DLL. Разделы в ЕХЕ- и DLL-файлах

обзорный тур

Получение списка импортируемых функций

Открыв исполняемый файл в PE Explorer, вы имеете возможность получить список имён импортируемых функций, а так же ряд свойств, перечисленных ниже.

Import Function List Viewer отображает список функций, которые импортируются изучаемым приложением, и список библиотек, из которых данное приложение импортирует эти функции. Для стандартных системных библиотек дополнительно показывается тип и параметры вызова этих функций. Эту информацию можно сохранить на диск в виде текстового отчёта.

См. также:

Просмотр таблицы экспорта
Как мне получить параметры экспортируемой функции?
Просмотр и редактирование описания синтаксиса функций
Расшифровка mangled имён функций


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

ЛЕВАЯ ПАНЕЛЬ

RVA
Name - Имя DLL, в которой находятся указанные функции.

ПРАВАЯ ПАНЕЛЬ

RVA - Адрес функции в DLL.
Hint - Индекс функции в таблице экспорта той DLL, в которой находится эта функция.
Name - Название функции.

СВОЙСТВА ИМПОРТИРУЕМЫХ ФУНКЦИЙ

Name Table - Адрес строки, которая должна совпадать с публичным именем в DLL.
Time Date Stamp - Штамп времени.
Forwarder Chain - Индекс первого forwarder в списке импортируемых функций.
RVA - Адрес ASCII строчки, содержащей имя DLL. Адрес относителен к адресу Image Base.
Address Table - Относительный виртуальный адрес Import Address Table.

Создавая DLL, Вы создаете набор функций и хотите, чтобы они были доступны другим ЕХЕ - или DLL-модулям. Если DLL-функция доступна для вызова из других программ, то говорят, что это экспортируемая (exported) функция.

Кроме функций, Win32 позволяет экспортировать и глобальные переменные.

Вот как экспортировать из DLL функцию Add и глобальную целочисленную переменную g_nUsageCount

Declspec(dllexport)

return(nLeft + nRight);

Declspec(dllexport)

int g_nUsageCount = 0;

Конструкцию __dedspec(dllexport) компилятор C/C++ распознает как новое ключевое слово. Компилируя функцию Add и g_nUsageCount, он встраивает в конечный OBJ-файл дополнительную информацию, необходимую компоновщику при сборке DLL из OBJ-файлов.

Обнаружив такую информацию, компоновщик создает LIB-файл со списком иден-

тификаторов, экспортируемых из DLL. Этот LIB-файл нужен при сборке любого ЕХЕ - файла, вызывающего функции из данной DLL.Кроме того, компоновщик вставляет в

конечный файл DLL и таблицу экспортируемых идентификаторов (exported symbols).

Каждый элемент в этой таблице содержит имя экспортируемой функции или переменной, а также адрес этой функции или переменной внутри DLL-файла. Все списки сортируются по алфавиту.

Импорт функций и переменных из DLL

Чтобы ЕХЕ - файл мог вызывать функции или получать доступ к переменным из DLL, нужно сообщить компилятору, что они находятся именно в DLL.Следующий фрагмент кода показывает, как импортировать функцию Add и переменную g_nUsageCount,

экспортируемые DLL-модулем:

Declspec(dllimport) int Add(int nLeft, int nRight); _declspec(dlliinport) int g_nUsageCount;

Как и _dedspec(dllexport), _dedspec(dllimport) - новое ключевое слово, распознаваемое компилятором C/C++. Оно сообщает компилятору, что функция Add и переменная g_nUsageCount находятся в DLL, доступ к которой ЕХЕ - файл должен получить при загрузке.

Это заставит компилятор сгенерировать специальный код для импортируемых идентификаторов (imported symbols).

Еще компилятор встроит специальную информацию в конечный объектный файл.

Она используется при компоновке ЕХЕ - файла, подсказывая компоновщику, какие функции следует искать в LIB-файлах. Собирая ЕХЕ - файл, компоновщик отыскивает импортируемые функции и переменные. Затем, определив, какой LIB-файл содержит эти идентификаторы, добавляет в таблицу импорта новые элементы. Каждый элемент содержит имя соответствующего DLL-файла, а также имя самого идентификатора. Таблица импорта вносится в конечный ЕХЕ - файл при его записи на жесткий диск.

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

Импортируя идентификатор, ключевое слово _declspec(dllimport) использовать не обязательно. Вместо него можно взять стандартное ключевое слово extern. Но компилятор генерирует более эффективный код, если ему заранее известно, что идентификатор будет импортирован из DLL.

Поток получает адрес экспортируемой из DLL функции или переменной вызовом

FARPROC GetProcAddress(HINSTANCE hinstDll, LPCSTR IpszProc);

Параметр hinstDll- описатель DLL. Это значение можно получить с помощью

LoadLibrary или LoadLibraryEx. Параметр IpszProc разрешается указыватьв двух формах. Во-первых, как адрес строки с нулевым символом в конце, содержащей

имя интересующей Вас функции:

Ipfn = GetProcAddress(hinstDll, "SomeFuncInDll");

Вторая форма параметра IpszProc позволяет указывать порядковый номер нужной функции:

Ipfn = GetProcAddress(hinstDll, MAKEINTRESOURCE(2));

Здесь подразумевается, что нам известен порядковый номер (2) функции SomeFuncInDll, присвоенный ей в данной DLL.

Оба способа дают адрес содержащейся в DLL функции SomeFuncInDll. Если функция не найдена, GetProcAddress возвращает NULL.Однако и тот, и другой способ не без недостатков.

Первый медленнее, так как системе приходится проводить поиск и сравнивать строки.

Во втором, если Вы передаете порядковый номер, не присвоенный ни одной из экспортируемых функций, GetProcAddress может вернуть значение, отличное от NULL. (Это относится и к 16-разрядной Windows.)

В итоге Ваша программа , ничего не “подозревая”, получит неправильный адрес.

Заголовочный файл DLL

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

Чтобы один и тот же заголовочный файл можно было использовать при компиляции

исходных файлов как ЕХЕ, так и DLL-модулей, он должен выглядеть так:

определена

реализаций MyLib.C как

Declspec(dllexport)

при включении

заголовочного файла в MyLib.C,

// экспортироваться, а не импортироваться.

MYLIBAPI _declspec(dllimport)

//////////////////////////////////////////////////////////////////////////////////

MYLIBAPI int g_nUsageCount;

Этот заголовочный файл надо включать в самое начало исходных файлов Вашей DLL следующим образом:

// Мы должны определить MYLIBAPI как _declspec(dllexport) до включения

// файла MyLib.H. Тогда MyLib.H, "увидев", что мы уже определили //MYLIBAPI, не станет (пере)определять ее как _declspec(dlliinport).

#define MYLIBAPI __declspec(dllexport) #include "MyLib.H"

///////////////////////////////////////////////////////////////////

int Add(int nLeft, int nRight) { return(nLeft + nRight);

MYLIBAPI int g_nUsageCount;

Поскольку MYLIBAPI определена как _declspec(dllexport) явно, то при компиляции исходного кода Вашей программы компилятор узнает, что функции экспортируются. А

это позволяет не повторять _declspec(dllexport) перед каждой процедурой или переменной.

Заголовочный файл нужно включить в исходный код, импортирующий из DLL идентификаторы. MYLIBAPI будет определена как _declspec(dllimport), и компилятор “поймет”, какие идентификаторы содержатся в DLL.

Совместное использование дaнных несколькими проекциями ЕХЕ или DLL

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

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

несколькими экземплярами ЕХЕ. Например, в Win32 нет простого способа, позволяющего определить, запущено ли несколько копий приложения. А если бы у Вас была переменная, доступная всем копиям приложения, она могла бы отражать число запущенных копий. Тогда при запуске нового экземпляра приложения его поток просто проверил бы значение глобальной переменной (обновленное другой копией приложения) и, будь оно больше 1, сообщил бы пользователю, что запустить можно лишь одну копию, после чего этот экземпляр приложения благополучно бы и завершился.

Разделы в ЕХЕ- и DLL-файлах

Любой образ ЕХЕили DLL-файла состоит из группы разделов (sections). По соглашению имя каждого стандартного раздела начинается с точки.

Например, при компиляции программы исполняемый код помещается в раздел.text, неинициализированные данные - в раздел.bss, а инициализированные - в раздел.data.

С каждым разделом связана комбинация следующих атрибутов:

READ – разрешает чтение из раздела

WRITE – разрешает запись в раздел

EXECUTE – содержимое раздела можно исполнять

SHARED – раздел доступен нескольким экземплярам приложения

(!!!) Вот некоторые из часто встречающихся разделов:

1. .text – код приложения из DLL

2. .bss – неинициализированные данные

3. .rdata – неизменяемые данные периода выполнения

4. .rsrc - ресурсы

5. .edata – таблица экспортируемых имен

6. .data – инициализированные данные

7. .xdata – таблица для обработки исключений

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

Советниками в MetaTrader4™ называются программы, разработанные на языке программирования MetaQuotes Language 4 (MQL 4) и позволяющие автоматизировать аналитические и торговые операций. Советники позволяют в автоматическом режиме проводить анализ текущей ситуации и на основе полученных сигналов способны выдавать команды на выполнение торговых операций и управление открытыми позициями.

В клиентский терминал MetaTrader4™ встроена собственная среда разработки экспертов - MQL4 IDE. Она включает в себя:

  • Терминал MetaTrader4™ - модуль управления и исполнения программ автотрейдинга.
  • MetaQuotes Language 4 (MQL4) - непосредственно язык программирования торговых стратегий.
  • MetaEditor - редактор и компилятор советников.
  • Strategy Tester - модуль тестирования и оптимизации экспертов.

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

Что дает трейдеру автоматическая торговля:

  1. Возможность создатьстратегию-автомат, которая торгует круглосуточно без участия трейдера.
  2. Возможность частично снять рутину совершения торговых операций и сосредоточится на творческой работе, например, на разработке и оптимизации новой торговой системы.
  3. Возможность реализовать торговую систему, которую при ручной торговле применить не получится.
  4. Возможность использовать торговые стратегии, созданные другими авторами, просто копируя программные коды.
  5. Возможность получить инструменты автоматизации торговли:
    • советники, дающие только сигналы;
    • инструменты сбора различной статистики;
    • реализацию недостающего функционала.
  6. Возможность создания индивидуального тестера стратегий:
    • расчёт уникальных, нужных именно вам, показателей;
    • использование уникальных авторских торговых систем.

Для создания советников используется редактор MetaEditor. Чтобы запустить редактор советников, необходимо выполнить команду "Создать" контекстного меню окна "Навигатор - Советники", команду меню "Сервис - Редактор MetaQuotes Language", нажать клавишу F4 или кнопку на панели "Стандартная". При создании эксперта автоматически откроется мастер создания советников, позволяющий быстро приступить к работе с новой MQL4-программой. В нем в качестве типа создаваемого объекта необходимо указать "Советник" и заполнить поля требуемыми данными:

Имя - название советника;

Параметры - список входных параметров советника. Чтобы добавить новый параметр, необходимо нажать кнопку "Добавить", чтобы удалить - кнопку "Удалить".

После этого в редакторе открывается окно нового советника с заданными параметрами. Файл с исходным текстом (*.MQ4) советника автоматически помещается в папку /EXPERTS клиентского терминала ForexClub MetaTrader4™. С этого момента можно приступать к написанию кода эксперта.

По завершении разработки необходимо скомпилировать советник. Для этого в редакторе советников необходимо выполнить команду меню «Файл» - «Компилировать». В результате успешной компиляции создается исполняемый файл программы с расширением *.EX4, автоматически помещаемый в папку /EXPERTS. Список скомпилированных экспертов можно просмотреть в окне «Навигатор» - «Советники» клиентского терминала. Если компиляция не была успешно завершена, пиктограмма эксперта будет закрашена серым цветом. Это означает, что его использовать нельзя.

Чтобы приступить к редактированию уже существующего советника из терминала, необходимо выполнить команду "Изменить" контекстного меню окна "Навигатор - Советники". При этом откроется редактор советников, в который уже будет загружен исходный текст выбранного эксперта. После изменения исходного текста советника необходимо повторно скомпилировать его и получить новый исполняемый EX4-файл. В противном случае в терминале будет использоваться неизмененная, предыдущая версия эксперта.

Перед началом использования советников необходимо произвести их предварительную настройку. Общие для всех экспертов параметры работы задаются в окне настройки клиентского терминала. Это окно можно открыть командой меню "Сервис - Настройки" или при помощи клавиш-акселераторов Ctrl+O. Для настройки параметров работы экспертов необходимо выбрать вкладку "Советники". В ней доступны:

Включить советники. Эта опция позволяет разрешить или запретить использование всех советников. Если она отключена, с приходом нового тика для всех экспертов перестает запускаться функция start(). При этом вместо смайликов напротив названий экспертов в правом верхнем углу графиков появятся крестики. Чтобы включить советники, необходимо выставить флажок и нажать кнопку "ОК". С приходом нового тика они начнут работать, а крестики в правом верхнем углу графика вновь станут смайликами.

Внимание: эксперт запускается на выполнение с приходом нового тика и, чаще всего, успевает завершить свою работу до прихода следующего тика. Отключение советников не прерывает текущее исполнение уже работающих экспертов; эта опция распространяется только на советники и не позволяет автоматически отключать пользовательские индикаторы и скрипты.

Отключить советники при смене счета. Эта опция представляет собой защитный механизм, отключающий советники при смене счета. Она бывает полезна, например, при переключении с демо-счета на реальный. Чтобы включить механизм, необходимо выставить флажок и нажать кнопку "ОК".

Отключить советники при смене профиля. В профилях сохраняется большое количество информации о текущих настройках всех графиков в рабочей области. В частности, в профилях сохраняется информация о прикрепленных советниках. Эксперты, входящие в состав профиля, с приходом нового тика начнут работать. Включив эту опцию (выставив флажок), можно не допустить запуска экспертов при смене профиля.

Разрешить советнику торговать. Советники способны работать в автоматическом режиме, без участия трейдера. Они могут как анализировать динамику цен, так и вести торговую деятельность. Эта опция предназначена для ограничения торговых функций экспертов. Такое ограничение бывает полезно при тестировании аналитических способностей эксперта в режиме реального времени (не путать с тестированием советника на исторических данных).

Ручное подтверждение. Опция "Ручного подтверждение" активируется только в том случае, если советникам разрешено торговать. Если эта опция включена, и советник пытается провести торговую операцию, можно будет либо подтвердить ее, либо прервать вручную. Иными словами, при помощи ручного подтверждения можно контролировать торговую активность советника. Это может быть полезно при тестировании торговых функций советника в режиме реального времени (не путать с тестированием советника на исторических данных).

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

Подтверждать вызов функций DLL. Эта опция активируется только в том случае, если был разрешен импорт из DLL-библиотек. Она позволяет контролировать выполнение каждой вызываемой функции вручную. Если флажок не установлен, импорт из внешних библиотек контролироваться не будет. При работе с неизвестными экспертами рекомендуется включать эту опцию.

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

После настройки общих параметров, можно запускать эксперты. Для этого достаточно лишь присоединить советник к графику, просто перетащив его на график из меню «Советники». Команда "Присоединить к графику" контекстного меню окна "Навигатор - Советники" или двойной клик левой кнопкой мыши на выбранном эксперте в том же окне позволяют наложить его на активный график. При этом на экране появится окно индивидуальных настроек советника. Во вкладке "Общие" можно:

Позиции - выбрать направление открытия позиций:

  • Long&Short - в обе стороны;
  • Only Long - только на покупку;
  • Only Short - только на продажу.

Разрешить сигналы - разрешить/запретить советнику подавать сигналы;

Не повторять сигнал - запретить подачу сигналов о событиях после поступления первого сигнала;

Разрешить советнику торговать - разрешить/запретить проведение торговых операция в реальном времени;

Ручное подтверждение - запрашивать подтверждение на открытие позиции при проведении торговых операций;

Разрешить импорт DLL - разрешить/запретить импорт функций из DLL-файлов;

Подтверждать импорт функций DLL - запрашивать подтверждения при каждом вызове функций из DLL-файлов;

Разрешить импорт внешних экспертов - разрешить/запретить вызов функций из внешних экспертов.

Во вкладке "Входные параметры" можно изменить внешние переменные эксперта. К ним относятся переменные класса extern. Чтобы изменить параметр необходимо дважды кликнуть левой кнопкой мыши на его значении и записать новое. При этом можно изменять значение каждой переменной или загрузить уже сохраненный набор входных параметров (кнопка "Загрузить"). Сохранить текущий набор внешних переменных можно при помощи одноименной кнопки.

Кнопка "Сброс" возвращает все настройки по умолчанию. Во вкладке "Общие" выставляются заданные в настройках терминала параметры. А в качестве входных переменных выставляются параметры, указаные в исходном тексте программы. Чтобы подтвердить прикрепление советника с заданными параметрами, необходимо нажать кнопку "ОК". А отменить наложение эксперта можно нажав одноименную кнопку.

Внимание: индивидуальную настройку можно производить для уже прикрепленных экспертов. Однако, пока идет текущее исполнение, открыть страницу свойств советника нельзя. Это можно сделать только в промежутках между вызовами функции start(). При этом эксперт запускаться не будет, пока открыты его свойства. Если были изменены входные параметры советника, то по нажатии кнопки "ОК" происходит переинициализация эксперта с новыми входными параметрами.

После настройки эксперта произойдет его инициализация и с приходом нового тика советник начнет исполнятся. Свидетельством прикрепления советника является появление в правом верхнем углу графика имени эксперта и значка - смайлика. Если в настройках эксперта запрещено торговать, то вместо веселого смайлика появится грустный смайлик.

Внимание: к одному графику можно присоединить только один советник. При наложении второго советника, первый удаляется.

Чтобы завершить работу эксперта, необходимо удалить его с графика. Перед завершением работы производится деинициализация эксперта. Для удаления эксперта с графика необходимо выполнить команду контекстного меню графика "Советники - Удалить" либо присоединить к графику другой советник. Кроме того, советник может удаляться с графика при смене профиля или шаблона.

Внимание:

  • при выключении клиентского терминала происходит завершение работы всех экспертов;
  • при закрытии графика происходит завершение прикрепленного к нему советника;
  • при наложении второго советника, первый удаляется после подтверждения;
  • удаление советника из окна "Навигатор" не завершает работу одноименного наложенного на график эксперта;
  • отключение советников в настройках клиентского терминала не является гарантией полного отключения экспертов. Эта опция прекращает запуск функции start() каждого советника, но функция init() продолжает выполнятся.


Поделиться