- •Для чего используются библиотечные файлы?
- •Статически и динамически подключаемые библиотеки
- •Методика выполнения работы Создание статической библиотеки с помощью репозитория объектов
- •Использование файла библиотеки модулей
- •2. Создание динамически подключаемой библиотеки с помощью репозитория объектов
- •Задание на дом
- •Командные символы
- •Примеры работы с tlib
Методика выполнения работы Создание статической библиотеки с помощью репозитория объектов
Поместите в папку файлы, прилагаемые к лабораторной работе.
Запустите среду C++ Builder.
Закройте созданную средой форму (File -> Close All);
Выберете пункт New из меню File.
В закладке выберите объект Library
На экране появится окно такое окно:
|
В главном меню выберете пункт Project -> Add to Project и последовательно откройте модули, которые требуется поместить в библиотечный файл.
Сохраните проект (Save All) под именем, которым вы хотите назвать библиотечный файл.
В главном меню выберете пункт Project -> Make [имя файла библиотеки]
Если ошибок в модулях нет, то на диске будет создан файл с расширением LIB.
Закройте проект.
Использование файла библиотеки модулей
Создайте заготовку для новой программы (New Application) и сохраните ее.
Добавьте библиотеку модулей в проект (Project -> Add to Project).
Напишите обработчик события. Помните о прототипах вызываемых функций.
typedef float ** Matrix_Float;
Matrix_Float Get_mem ( int n, int m );
void Del_mem (Matrix_Float, int n );
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
Matrix_Float Mat = Get_mem ( 10, 10 );
for ( int i =0 ; i < 10; i ++)
for ( int j =0 ; j < 10; j ++)
Mat[i][j] = i*j;
Del_mem ( Mat, 10 );
return;
}
Скомпилируйте программу.
2. Создание динамически подключаемой библиотеки с помощью репозитория объектов
1. Выберете в главном меню пункт File->New. Затем выберете их репозитория объектов объект DLL Wizard.
Будет создан новый пустой проект.
2. Добавьте в заголовок
#include <condefs.h>
Добавьте перед функцией DllEntryPoint()
#define DLLMAINCPP
И вслед за этой строкой
#include “Имя библиотеки.h”
Например,
#include "Own_static_LD.h"
4. Сразу же после функции:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
Добавьте тексты модулей, помещаемых в библиотеку. Обратите внимание, что в заголовке функции требуется вставить ключевое слово _export.
// Выделяет память под двумерный массив типа float
// n - число строк
// m - число колонок
float ** _export Get_mem ( int n, int m )
{
float ** buffer; // память для хранения адреса адреса массива,
// в котором будут хранится адреса строк таблицы
// float ** buffer - адрес адреса
buffer = new float *[n]; // запрашиваем память для хранения n
// адресов строк массива
for ( int i =0; i < n ; i ++)
buffer[i] = new float [m]; // выделяем память для
// под строки масива и
// записываем адреса в
// в массив buffer
for ( int i =0; i < n ; i ++)
for ( int j = 0; j < m ; j ++)
buffer[i][j] = 0.0; // в массив записываем нули
return buffer; // возвращаем адреса массива
}
// возвращаем выделенную память OС
void _export Del_mem ( float ** A, int n )
{
for ( int i =0; i < n ; i ++)
delete[] A[i]; // высвобождаем память под строки массива
delete[] A; // высвобождаем память, в которой хранились
// адреса строк
return;
}
# include <math.h>
/ / Определитель матрицы
double _export Det_Matrix ( double **Matrix, int n)
{
double t, d , max, det;
int i, j , k;
d = 1.0;
for ( k = 0; k < n; k ++)
{
max = 0.0;
for (i = k; i < n ; i ++)
{
t = Matrix[i][k];
if ( fabs (t) > fabs (max))
{
max = t; j = i;
}
}
if ( fabs (max) < 0.000001)
{
return 0;
}
if ( j != k)
{
d =- d;
for ( i = k; i < n;i ++)
{
t = Matrix[j][i];
Matrix[j][i] = Matrix[k][i];
Matrix[k][i] = t;
}
}
for ( i = k + 1; i < n; i ++)
{
t = Matrix[i][k] /max;
for ( j = k +1; j < n; j ++)
Matrix[i][j] = Matrix[i][j]- t *Matrix[k][j];
}
d = d* Matrix[k][k];
}
return det;
}
5. Сохраните проект под именем Own_static_LD.cpp
Теперь создаем заголовочный файл для DDL. Выберете в главном меню пункт File->New. Затем выберете объект TEXT.
7. Сохраните файл как Own_static_LD.h. Это имя уже использовалось в директиве (#include "Own_static_LD.h").
Для чего нужен этот файл. Все экспортируемые функции при сборке библиотеки должны иметь спецификатор _export или __declspec(dllexport), а импортируемые _import или __declspec(dllimport). То есть если файл заголовка используется самим DLL, то перед функциями должен стоять один из пары первых спецификаторов, а если использующим DLL приложением, то один из пары вторых.
8. Введите такой код в этот модуль
#if defined(DLLMAINCPP)
# define DLL_SPEC __declspec(dllexport)
#else
# if defined(APPMAINCPP)
# define DLL_SPEC __declspec(dllimport)
# else
# define DLL_SPEC
# endif
#endif
extern "C" float ** DLL_SPEC Get_mem ( int n, int m );
extern "C" void DLL_SPEC Del_mem ( float ** A, int n );
extern "C" double DLL_SPEC Det_Matrix ( double **Matrix, int n);
9. Войдите в пункт меню Project| Make и выполните его. Если ошибок нет, то на диске появятся файлы Own_static_LD.lib и Own_static_LD.dll. Файл Own_static_LD.lib содержит ссылку на библиотеку и список находящихся в ней функций.
Создание вызывающего приложения. Приложение создается как обычно. В модуль, в котором вызываются функции из библиотеки, требуется поместить
#define APPMAINCPP
#include "Own_static_LD.h"
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
#define APPMAINCPP
#include "Own_static_LD.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
typedef float ** Matrix_Float;
void Display (Matrix_Float Mat, int n, int m, char *format,TMemo *Memo);
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Matrix_Float Mat = Get_mem ( 10, 10 );
for ( int i =0 ; i < 10; i ++)
for ( int j =0 ; j < 10; j ++)
Mat[i][j] = i*j;
Display (Mat, 10, 10, "%5.1f",Memo1);
Del_mem ( Mat, 10 );
return;
}
Не забудьте подключить lib- файл к проекту (Project | Add to Project).
Динамическая загрузка dll. Динамической загрузкой библиотеки управляется программа.
Вызовете функцию с именем библиотеки:
INSTANCE hDLL = LoadLibrary("Own_static_LD.dll");
Если hDLL!=0, то библиотека загружена в память.
Вызовете функцию для получения адреса функции и библиотеки
My_adr_get = (get_mem)GetProcAddress(hDLL,"_Get_mem");
Обратите внимание, что перед именем функции из dll должен быть символ подчеркивания!
Предварительно требуется описать:
typedef float ** (*get_mem )( int n, int m );
get_mem My_adr_get;
Указатель на функцию, возвращаемый GetProcAddress() должен быть приведен к типу get_mem.
Если My_adr_get!=0, то c функцией можно работать через указатель.
Если библиотеку не планируется использовать, то ее можно выгрузить
FreeLibrary(hDLL);
Пример.
#include <vcl.h>
#include "windows.h"
#pragma hdrstop
#include "Main.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
typedef float ** (*get_mem )( int n, int m );
typedef void (*del_mem )( float ** A, int n );
double Det_Matrix ( double **Matrix, int n);
typedef float ** Matrix_Float;
_fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HINSTANCE hDLL;
get_mem My_adr_get;
del_mem My_adr_del;
hDLL = LoadLibrary("Own_static_LD.dll");
if (hDLL == NULL)
{
ShowMessage ("Не могу загрузить DLL "); return;
}
My_adr_get = (get_mem)GetProcAddress(hDLL,"_Get_mem");
if (My_adr_get == NULL)
{
ShowMessage ("Не могу получить адрес Get_mem"); return;
}
My_adr_del = (del_mem )GetProcAddress(hDLL,"_Del_mem");
if (My_adr_del == NULL) {
ShowMessage ("Не могу получить адрес Del_mem"); return;
}
Matrix_Float Mat = (Matrix_Float) My_adr_get( 10, 10 );
for ( int i =0 ; i < 10; i ++)
for ( int j =0 ; j < 10; j ++)
Mat[i][j] = i*j;
My_adr_del ( Mat, 10 );
FreeLibrary(hDLL);
return;
}
