Перейти к содержанию

DLL

Материал из Викиучебника — открытых книг для открытого мира

Примеры использования DLL в разных языках

[править]

Экспорт в DLL

[править]
 library Example;
 
 { Производим некие действия и возвращаем результат }
 function AddNumbers(a, b: Double): Double; cdecl;
 begin
   AddNumbers := a + b
 end;
 
 { Эта функция экспортируется }
 exports
   AddNumbers;
 
 { Инициализатор DLL, аналог функции main() в языках C и C++ }
 begin
 end.
 #include <windows.h>
 
 #define DLLEXPORT extern "C" __declspec(dllexport)
                 // extern "C" обозначает использование простой генерации
                 // сигнатуры функции (в стиле языка С) при получении объектных
                 // файлов. В частности, это запрещает компилятору C++
                 // производить "декорацию" (или "украшение") имени функции
                 // дополнительными символами при экспорте в DLL

 /* Эта функция экспортируется */
 DLLEXPORT double AddNumbers(double a, double b)
   // Прототип функции (функция без тела). По данной заявленной сигнатуре функции поиск её тела
   // при линковке будет произведён ниже или в другом бинарном файле 
 ;
 
 /* Инициализационная функция DLL, аналог main() */
 bool APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
 {
   return TRUE;
 }
 
 /* 
    Тело (реализация) заявленного выше прототипа функции.
    Производит некие действия и возвращает результат
  */
 DLLEXPORT double AddNumbers(double a, double b)
 {
   return a + b;
 }

Пример компиляции абстрактных файлов a.cpp и b.cpp в res.dll из командной строки при помощи GCC:

g++ -c a.cpp -o a.o
g++ -c b.cpp -o b.o
dllwrap a.o b.o -o res.dll
del a.o b.o

Импорт из DLL

[править]
 program Example;
 {$APPTYPE CONSOLE}
 
 { Указываем, что функция находится в DLL }
 function AddNumbers(a, b: Double): Double; cdecl; external 'Example.dll';
 
 { Используем функцию как обычно }
 var result: Double;
 begin
   result := AddNumbers(1, 2);
   Writeln('The result was: ', result)
 end.
 #include <stdio.h>
 
 /*
  * Указываем, что тело функции находится в другом файле.
  * Не забыть про объектный модуль DLL при линковке!
  */
 extern "C" __declspec(dllimport)double AddNumbers(double a, double b);
 
 /* Используем функцию как обычно */
 int main(int argc, char **argv)
 {
     double result = AddNumbers(1, 2);
     printf("The result was: %f\n", result);
     return 0;
 }

Функция должна быть объявлена в TLB, а TLB подключена к проекту. Именно этот механизм в VB используется для импорта всех «встроенных» функций (таких как MsgBox, Round, и т. д.) из runtime-библиотеки.

Подгрузка и импорт из DLL во время работы

[править]
 program Example;
 {$APPTYPE CONSOLE}
 
 var result: Double;
     LibHandle: Hmodule;
     AddNumbers: function(a, b: Double): Double;
 begin
   LibHandle := LoadLibrary('Example.dll'); // загружаем DLL
   if LibHandle <> 0 then
     begin
       @AddNumbers := GetProcAddress(LibHandle, 'AddNumbers'); // запоминаем адрес
                                                               // необходимой функции
       if @AddNumbers <> nil then
         begin
           result := AddNumbers(1, 2);       // используем функцию
           Writeln('The result was: ', result);
         end;
       FreeLibrary(LibHandle);               // выгружаем DLL
     end;
 end.
 #include <windows.h>
 #include <stdio.h>
 
 /*
  * Тип используемой функции
  * (комбинация типов параметры и возвращаемого значения)
  */
 typedef double (*importFunction)(double, double);
 
 int main(int argc, char **argv)
 {
     importFunction addNumbers;
     double result;
 
     /* Загружаем DLL в память */
     HMODULE hinstLib = LoadLibrary("Example.dll");
     if (hinstLib == NULL) {
         printf("ERROR: unable to load DLL\n");
         return 1;
     }
 
     /* Получаем указатель на функцию */
     addNumbers = (importFunction)GetProcAddress(hinstLib, "AddNumbers");
     if (addNumbers == NULL) {
         printf("ERROR: unable to find DLL function\n");
         return 1;
     }
 
     /* Вызываем функцию через указатель */
     result = addNumbers(1, 2);
 
     /*
      * Выгружаем DLL (в принципе, это будет сделано
      * автоматически при выходе из программы)
      */
     FreeLibrary(hinstLib);
 
     /* Отображаем результат */
     printf("The result was: %f\n", result);
 
     return 0;
 }
 Option Explicit
 
 ' Указываем, что функция находится во внешней DLL.
 Declare Function AddNumbers Lib "Example.dll" _ 
           (ByVal a As Double, ByVal b As Double) As Double
 
 ' Используем функцию как обычно
 Sub Main()
     Dim Result As Double
     Result = AddNumbers(1, 2)
     Debug.Print "The result was: " & Result
 End Sub