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