Как написать программу dll

Сейчас мы рассмотрим для чего нужны DLL (Dynamic Link Library — динамически компануемая библиотека) и как их создавать. DLL- это участок кода хранимый в файле с расширением .dll. Код может быть использован другими программами, но сама посебе библиотека прораммой не является. Вобщем-то, динамически компонуемые библиотеки представляют собой набао скомпилированныых функций.

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

При статической загрузке DLL автоматически загружается при запуске исользующего ее приложения. Такая DLL содержит экспортируемые функции, описание которых находится в файле библиотеки импорта(import library file — .lib). Для использования статической загрузки вы должны на этапе компоновки к программе додключить .lib файл вашей DLL. В C++ Builder это сводится к включения в проект .lib файла через менджер проектов.

Как создать точку входа в Динамической Библиотеки DLL на C++

При диамической загрузке вы можете загружать DLL при необходимости, выгрузить ее когода она ненужна. Однако работать с такими библиотеками сложнее чем со статическими. Рассмотрим созздание и использование DLL статической загрузки.

Статическая загрузка

Создадим сперва проект (File / New / DLL). Будет создан проект, содержащий следующее:

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)

и длинный коментарий предупреждающий вас о том, что для работо способности вашей DLL необходимо снеи обеспечить поствку некоторых dll если вы используете экземпляры класса String.

Для экспорта и импорта из DLL необходимо использовать моди фикаторы __export и __import соответсвенно. Но в C++ Builder можно использовать новое ключевое слово __delspec() с параметрами dllexport и dllimport соответсвенно. Сами понимаете, что для того чтобы эспортировать функции из библиотеки еужен один заголовочный файл с описаниями _delspec(dllexport) для экспортируемых функций, для импорта функций в приложение вам необходимо будет поставить анологичный заголовочный файл но с _delspec(dllimport) описаниями, что достаточно неудобно. Эта проблема решается легко: добавте в заголовочный файл библиотеки следующее:

#if defined(BUILD_DLL) # define DLL_EXP __declspec(dllexport) #else # if defined(BUILD_APP) # define DLL_EXP __declspec(dllimport) # else # define DLL_EXP # endif #endif

в исходном файле DLL напишите #define BUILD_DLL, а вместо __declspec(dllexport) пишите DLL_EXP. При написании программы добавте строчку #define BUILD_APP, и просто подключите заголовочный файл DLL.

Пример DLL: файл P.cpp

//————————————————————————— #define BUILD_DLL #include #include «p.h» #pragma hdrstop //————————————————————————— // Important note about DLL memory management when your DLL uses the // static version of the RunTime Library: // // If your DLL exports any functions that pass String objects (or structs/ // classes containing nested Strings) as parameter or function results, // you will need to add the library MEMMGR.LIB to both the DLL project and // any other projects that use the DLL. You will also need to use MEMMGR.LIB // if any other projects which use the DLL will be perfomring new or delete // operations on any non-TObject-derived classes which are exported from the // DLL.

Adding MEMMGR.LIB to your project will change the DLL and its calling // EXE’s to use the BORLNDMM.DLL as their memory manager. In these cases, // the file BORLNDMM.DLL should be deployed along with your DLL. // To avoid using BORLNDMM.DLL, pass string information using «char *» or // ShortString parameters. // // If your DLL uses the dynamic version of the RTL, you do not need to // explicitly add MEMMGR.LIB as this will be done implicitly for you //————————————————————————- int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) < return 1; >//————————————————————————- void Message(char *s) < i=10; Application->MessageBox(s,»From DLL»,IDOK); >

Читайте также:
Лабиринт партнерская программа отзывы

[Пишем .DLL: #1] Подготовка и настройка.

#if defined(BUILD_DLL) # define DLL_EXP __declspec(dllexport) #else # if defined(BUILD_APP) # define DLL_EXP __declspec(dllimport) # else # define DLL_EXP # endif #endif DLL_EXP void Message(char *s); DLL_EXP int i;

Если вы нажмете Run то после завершенния построения будет выдано сообщение что данная программа не можнт быть исполнена (естественно). Теперь напишем вызывающую программу. Втомже каталоге создайде новый проект (File / New Application) в форму поместите одну кнопку и создай обработчик события OnClick. Ваш исполняемый файл должен представлять собой слдующее:

//————————————————————————— #include #define BUILD_APP #pragma hdrstop #include «p.h» #include «Unit1.h» #include //————————————————————————— #pragma package(smart_init) #pragma resource «*.dfm» TForm1 *Form1; //————————————————————————- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) < >//————————————————————————- void __fastcall TForm1::Button1Click(TObject *Sender) < char c[10]; Message(«roma»); for( ; i>0;i—) < sprintf(c,»Example %d»,i ); Application->MessageBox(«Example of using DLL variable»,(char*)c,IDOK); > > //————————————————————————-

Не забудьте об объявлениях в начале файла. Зайдите в менеджер проектов.Там откройте свой проект и добавте .lib файл из предыдушего проект с DLL( правый клик, пункт ADD). Запустите проект.

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

Динамическая загрузка

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

Давайте рассмотрим на примере, как производится динамическая загрузка. Создайте новый прокт DLL и внесите в него следующее:

extern «C» void __export Message(char *s) < Application->MessageBox(s,»From DLL»,IDOK); >

Cкомпилируйте проект, в результате чего будет создана DLL.

Теперь создайте проект приложения анологичный проекту для использования статической загрузки (форма с кнопкой и обработчиком события кнопки OnClick) ниже приведен код приложения:(Unit11.cpp)

//————————————————————————— #include #pragma hdrstop #include «Unit11.h» #include //————————————————————————— #pragma package(smart_init) #pragma resource «*.dfm» TForm1 *Form1; //————————————————————————— __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) < >//————————————————————————— void __fastcall TForm1::Button1Click(TObject *Sender) < void (__stdcall *Message)(char *s); HINSTANCE dllp = LoadLibrary(«p.dll»); if (dllp) < Message= (void(__stdcall *) (char*)) GetProcAddress(dllp, «_Message»); if (Message) Message(«Hi From Dinamic DLL»); >FreeLibrary(dllp); > //—————————————————————————

запустите это проект, при нажатии на кнопку должно выдаватся сообшение. Теперь разберемся, как это работает.

  • void (__stdcall *Message)(char *s);-объявление указателя на функцию.
  • HINSTANCE dllp = LoadLibrary(«p.dll»);- загрузка библиотеки в память.
  • Message= (void(__stdcall *) (char*)) GetProcAddress(dllp, «_Message»); присвоение указателю адреса функции DLL.
  • Message(«Hi From Dinamic DLL»); рабочий вызов фунциий (собственно то для чего все это и делается).
  • FreeLibrary(dllp);- выгрузка библиотеки из памяти.

Обратите внимание на то, что призагрузке можно указать точное местоположние библиотеки (необезательно в том же каталоге где и приложение).

Источник: codenet.ru

Как за 10 минут написать DLL библиотеку для MQL5 и обмениваться данными?

Как за 10 минут написать DLL библиотеку для MQL5 и обмениваться данными?

Так уж сложилось, что сейчас мало кто из разработчиков помнит, как написать простую DLL библиотеку и в чем особенности связывания разнородных систем.

Я постараюсь за 10 минут на примерах показать весь процесс создания простых DLL библиотек и раскрою некоторые технические детали нашей реализации связывания. Демонстрация будет на примере Visual Studio 2005 / 2008, бесплатные Express-версии которых можно свободно скачать с сайта Microsoft.

1. Создание проекта DLL на С++ в Visual Studio 2005/2008

Запустите визард через меню ‘File -> New’, выберите тип проекта ‘Visual C++’, шаблон ‘Win32 Console Application’ и укажите имя проекта (например, ‘MQL5DLLSamples’). Выберите отдельный корневой каталог хранения проектов ‘Location’ вместо предлагаемого по умолчанию, отключите галочку ‘Create directory for solution’ и нажмите на кнопку ‘OK’:

Рис 1. Win32 Application Wizard, создание проекта DLL

На следующем шаге просто нажмите на кнопку ‘Next’ для перехода на страницу настроек:

Рис 2. Win32 Application Wizard, параметры проекта

На финальной странице выберите тип ‘DLL’, оставив остальные поля пустыми как есть, и нажмите на ‘Finish’. Ставить галочку на ‘Export symbols’ не нужно, чтобы потом не удалять автоматически добавленный демонстрационный код:

Рис 3. Win32 Application Wizard, н астройка свойств приложения

Читайте также:
Какая программа обновляет Андроид с телефона

В результате получите пустой проект:

Рис 4. Пустой проект DLL

Для удобства тестирования лучше всего прямо в настройках ‘Output Directory’ указать выкладку DLL файлов напрямую в каталог ‘. MQL5Libraries’ клиентского терминала. Это сэкономит много времени в последующей работе:

Рис 5. Каталог выкладки DLL файлов

2. Подготовка к добавлению функций

Добавьте макрос ‘_DLLAPI’ в конец файла stdafx.h, чтобы можно было удобно и просто описывать экспортируемые функции:

//+——————————————————————+ //| MQL5 DLL Samples | //| Copyright 2001-2010, MetaQuotes Software Corp. | //| https://www.metaquotes.net | //+——————————————————————+ #pragma once #include «targetver.h» #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include //— #define _DLLAPI extern «C» __declspec(dllexport) //+——————————————————————+

В вызовах функций MQL5 используется соглашение о связях __stdcall и __cdecl. Хотя вызовы stdcall и cdecl отличаются вариантами извлечения параметров со стека, но исполняющая среда MQL5 позволяет безболезненно использовать оба варианта за счет специального враппера DLL вызовов.

По умолчанию в настройках компилятора С++ для функций используется __cdecl, но я рекомендую для экспортируемых функций явным образом указывать режим __stdcall.

Правильно оформленная экспортная функции должна иметь следующий вид:

_DLLAPI int __stdcall fnCalculateSpeed(int res2)

а в MQL5 программе описываться и вызываться так:

#import «MQL5DLLSamples.dll» int fnCalculateSpeed(int res2); #import //— вызов speed=fnCalculateSpeed(res_int,res_double);

Если при описании импорта DLL функции будет ошибка в итоговом размере блока параметров, то функция не будет вызвана, а в журнале появится сообщение вида ‘Cannot find ‘fnCrashTestParametersStdCall’ in ‘MQL5DLLSamples.dll». В этом случае надо тщательно перепроверить все параметры как в протопите функции, так и в самой DLL.

При отсутствии полного имени функции в таблице экспорта для совместимости используется поиск упрощенного описания без декорирования. Такие имена вида fnCalculateSpeed создаются при описаниях функции в формате __cdecl:

_DLLAPI int fnCalculateSpeed(int res2)

3. Способы передачи параметров и обмен данными

Давайте посмотрим на несколько вариантов передаваемых параметров:

    Прием и передача простых переменных
    С простыми переменными все просто — их можно передавать по значению или по ссылке через res1,double int res_int=0; double res_double=0.0; int start=GetTickCount(); //— быстро посчитаем простую математику for(int i=0;i10000000;i++) < res_int+=i*i; res_int++; res_double+=i*i; res_double++; >//— вернем результаты назад res1=res_int; res2=res_double; //— вернем занятое время return(GetTickCount()-start); >
    Вызов из MQL5:
    #import «MQL5DLLSamples.dll» int fnCalculateSpeed(int res2); #import //— вызовем просчет int speed=0; int res_int=0; double res_double=0.0; speed=fnCalculateSpeed(res_int,res_double); Print(«Time «,speed,» msec, int: «,res_int,» double: «,res_double);
    MQL5DLL Test (GBPUSD,M1) 19:56:42 Time 16 msec, int: -752584127 double: 17247836076609
    _DLLAPI void __stdcall fnFillArray(int *arr,const int arr_size) < //— проверим входящие параметры if(arr==NULL || arr_size1) return; //— заполним значениями for(int i=0;i
    Вызов из MQL5:
    #import «MQL5DLLSamples.dll» void fnFillArray(int #import //— вызовем заполнением массива int arr[]; string result=»Array: «; ArrayResize(arr,10); fnFillArray(arr,ArraySize(arr)); for(int i=0;iArraySize(arr);i++) result=result+IntegerToString(arr[i])+» «; Print(result);
    MQL5DLL Test (GBPUSD,M1) 20:31:12 Array: 0 1 2 3 4 5 6 7 8 9
    _DLLAPI void fnReplaceString(wchar_t *text,wchar_t *from,wchar_t *to) < wchar_t *cp; //— проверка параметров if(text==NULL || from==NULL || to==NULL) return; if(wcslen(from)!=wcslen(to)) return; //— поищем подстроку if((cp=wcsstr(text,from))==NULL) return; //— заменим memcpy(cp,to,wcslen(to)*sizeof(wchar_t)); >
    Вызов из MQL5:
    #import «MQL5DLLSamples.dll» void fnReplaceString(string text,string from,string to); #import //— модифицируем строку string text=»A quick brown fox jumps over the lazy dog»; fnReplaceString(text,»fox»,»cat»); Print(«Replace: «,text);
    MQL5DLL Test (GBPUSD,M1) 19:56:42 Replace: A quick brown fox jumps over the lazy dog

    Оказалось, что строка не изменилась! Это обычная ошибка начинающих программистов, когда они передают копии объектов (а string — это объект) вместо ссылки на них. Для строки ‘text’ была автоматически создана копия, которая была модифицирована в DLL, а затем копия также автоматически удалилась, не затронув оригинал.

    Чтобы исправить ситуацию, надо передавать строку по ссылке. Для этого просто модифицируем блок импорта, добавив знак MQL5DLLSamples.dll» void fnReplaceString(string #import

    После перекомпиляции и запуска получим правильный результат:

    MQL5DLL Test (GBPUSD,M1) 19:58:31 Replace: A quick brown cat jumps over the lazy dog

    4. Перехват исключений в DLL функциях

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

    Для проверки работоспособности этого механизма создадим следующий код:

    _DLLAPI void __stdcall fnCrashTest(int *arr) < //— ожидаем получение нулевой ссылки, чтобы вызвать исключение *arr=0; >

    и вызовем его из терминала:

    #import «MQL5DLLSamples.dll» void fnCrashTest(int arr); #import //— вызовем креш (среда исполнения перехватит исключение и не даст упасть терминалу) fnCrashTest(NULL); Print(«Этого текста не увидите!»); //—

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

    MQL5DLL Test (GBPUSD,M1) 20:31:12 Access violation write to 0x00000000

    5. Враппер DLL вызовов и потери скорости на вызовах

    Как уже было рассказано выше, для обеспечения безопасности каждый вызов DLL функции оборачивается в специальный враппер. Эта обвязка маскирует основной код, подменяет стек, поддерживает stdcall/cdecl соглашения и контролирует исключения внутри вызываемых функций.

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

    6. Финальная сборка

    Соберите все вышеприведенные примеры DLL функций в файле ‘MQL5DLLSamples.cpp’, а MQL5 примеры в скрипт ‘MQL5DLL Test.mq5’. Готовый проект для Visual Studio 2008 и скрипт на MQL5 приложены к статье.

    //+——————————————————————+ //| MQL5 DLL Samples | //| Copyright 2001-2010, MetaQuotes Software Corp. | //| https://www.metaquotes.net | //+——————————————————————+ #include «stdafx.h» //+——————————————————————+ //| Передача и прием простых переменных | //+——————————————————————+ _DLLAPI int __stdcall fnCalculateSpeed(int res2) < int res_int=0; double res_double=0.0; int start=GetTickCount(); //— быстро посчитаем простую математику for(int i=0;i10000000;i++) < res_int+=i*i; res_int++; res_double+=i*i; res_double++; >//— вернем результаты назад res1=res_int; res2=res_double; //— вернем занятое время return(GetTickCount()-start); > //+——————————————————————+ //| Заполнение массива значениями | //+——————————————————————+ _DLLAPI void __stdcall fnFillArray(int *arr,const int arr_size) < //— проверим входящие параметры if(arr==NULL || arr_size1) return; //— заполним значениями for(int i=0;i //+——————————————————————+ //| В текстовой строке заменяем подстроку на подстроку | //| string передается в виде прямой ссылки на контент строки | //+——————————————————————+ _DLLAPI void fnReplaceString(wchar_t *text,wchar_t *from,wchar_t *to) < wchar_t *cp; //— проверка параметров if(text==NULL || from==NULL || to==NULL) return; if(wcslen(from)!=wcslen(to)) return; //— поищем подстроку if((cp=wcsstr(text,from))==NULL) return; //— заменим memcpy(cp,to,wcslen(to)*sizeof(wchar_t)); > //+——————————————————————+ //| Устроим падение | //+——————————————————————+ _DLLAPI void __stdcall fnCrashTest(int *arr) < //— ожидаем получение нулевой ссылки, чтобы вызвать исключение *arr=0; > //+——————————————————————+
    //+——————————————————————+ //| MQL5DLL Test.mq5 | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+——————————————————————+ #property copyright «2010, MetaQuotes Software Corp.» #property link «https://www.mql5.com» #property version «1.00» //— #import «MQL5DLLSamples.dll» int fnCalculateSpeed(int res2); void fnFillArray(int void fnReplaceString(string text,string from,string to); void fnCrashTest(int arr); #import //+——————————————————————+ //| Script program start function | //+——————————————————————+ void OnStart() < //— вызовем просчет int speed=0; int res_int=0; double res_double=0.0; speed=fnCalculateSpeed(res_int,res_double); Print(«Time «,speed,» msec, int: «,res_int,» double: «,res_double); //— вызовем заполнением массива int arr[]; string result=»Array: «; ArrayResize(arr,10); fnFillArray(arr,ArraySize(arr)); for(int i=0;iArraySize(arr);i++) result=result+IntegerToString(arr[i])+» «; Print(result); //— модифицируем строку string text=»A quick brown fox jumps over the lazy dog»; fnReplaceString(text,»fox»,»cat»); Print(«Replace: «,text); //— а вконце вызовем креш (среда исполнения перехватит исключение и не даст упасть терминалу) fnCrashTest(NULL); Print(«Этого текста не увидите!»); //— > //+——————————————————————+

    Спасибо за внимание! Буду рад ответить на вопросы.

    Источник: www.mql5.com

    Программирование на C, C# и Java

    Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы

    Как создать dll в Visual Studio

    DLL (Dynamic Link Library) — динамически подключаемая библиотека функций. Для библиотек DLL предполагается многократное использование различными программами. Поговорим о том, как создать библиотеку DLL в Visual Studio, используя языки программирования C и C#.

    Создание dll на языке Си

    Создаем в Visual Studio новый проект — консольное приложение.

    Создаем в Visual Studio новый проект - vscode.ru

    В запустившемся «Мастере приложений Win32» жмем кнопку «Далее». В следующем окне выбираем тип приложения: «Библиотека DLL»; также ставим галочку напротив параметра «Пустой проект». Жмем кнопку «Готово».

    Как создать dll в Visual Studio - vscode.ru

    Теперь необходимо создать два файла исходного кода: «main.cpp» и «main.def». Для этого в «обозревателе решений» нажмем правой кнопкой мыши на папку «Файлы исходного кода», далее — «Добавить» — «Создать элемент».

    Создание файла исходного кода - vscode.ru

    В появившемся окне «Добавление нового элемента» во вкладке «Код» представлены типы файлов, которые нам необходимы. Создадим «main.cpp» и «main.def».

    Создание файлов исходного кода - vscode.ru

    В итоге обозреватель решений будет выглядеть вот так:

    Обозреватель решений для DLL - vscode.ru

    Перейдем к файлу «main.cpp». Для примера, напишем две функции add и sub, выполняющих сложение и вычитание соответственно для двух целых чисел.

    Источник: vscode.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru