Разработка DLL на языке С++

Страницы работы

Содержание работы

Как создать DLL

Сначала разработаем DLL на языке С++ и рассмотрим, как вызвать ее из клиентского модуля, написанного на том же языке.

¨  В меню File4New выберите команду Project.

¨  В появившемся окне диалога New Project, в окне Project Type раскройте узел дерева под именем Visual C++ Projects4Win32. В окне Templates выберите шаблон — Win32 Projects.

¨  В окне Name задайте имя решения MyDLL.

¨  В окне Location задайте местоположение новой папки с файлами решения (solution) и нажмите OK.

¨  В окне мастера Win32 Application Wizard выберите страницу Application Settings.

¨  Установите два флага: DLL, Exports symbols и нажмите Finish.

¨  Откройте окно свойств проекта и откажитесь от Unicode (установите Use Multibyte characters).

Так как проект достаточно прост (а также потому, что я считаю полезным рассматривать крайние варианты) удалите из проекта и уничтожьте файл MyDLL.h. В файл MyDLL.cpp мы внесем достаточно много изменений. Их суть такова. Обычно DLL экспортирует функции, которые надо специальным образом пометить. Но Microsoft Visual Studio предоставляет расширенные возможности. Вы можете экспортировать не только глобальные функции, но и переменные произвольных типов, и даже классы.

В Visual Studio существует три разных способа объявления экспортируемых функций. Рассмотрим самый прогрессивный из них. Он использует директивы и описатели, которые являются Microsoft-расширением языка С++. Все экпортируемые сущности должны иметь описатель __declspec(dllexport). В клиентском приложении эти же функции должны иметь описатель: __declspec(dllimport). При этом способе не нужен DEF-файл, который используется в ином (традиционном) подходе.

Мы будем экспортировать 2 переменные (progress, error), 4 функции (Gauss, Solve, AllocMatrix и ClearMatrix) и один класс (Geometry). Переменные и класс имеют одну цель — проиллюстрировать возможности экспорта DLL, три из четырех функций носят более утилитарный характер. Думаю, что они могут оказаться действительно полезными для вас. Класс Geometry и функция Solve тоже могут стать полезными, если вы вместо пустой заготовки функции Solve вставите коды алгоритма матричной прогонки (см. книгу: Самарский А.А. Методы решения сеточных уравнений).

Здесь же мы ставим более простую цель — написать программу решения системы линейных алгебраических уравнений произвольного порядка n методом исключения неизвестных (Гаусса). Значение размерности системы будет известно только во время выполнения клиентской программы, когда пользователь введет желаемый порядок. С учетом сказанного, внесите в файл MyDLL.cpp следующие изменения.

#include "stdafx.h"  // Сокращает время повторных компиляций

//==== Экспортируемые переменные

__declspec(dllexport) int progress = 0;

__declspec(dllexport) char* error = "No error";

//==== Экспортируемые функции

__declspec(dllexport) void AllocMatrix (double**& a, int ny, int nx)

{

a = new double* [ny];

for (int i=0; i<ny; i++)

{

a[i] = new double [nx];

memset (a[i], 0, nx * sizeof(double));

}

}

__declspec(dllexport) void ClearMatrix (double**& a, int n)

{

for (int i=0; i<n; i++)

delete [] a[i];

delete [] a;

a = 0;

}

__declspec(dllexport) bool Gauss (double** a, double* x, int n)

{

double c, s, d;

int i, j, k;

for (k=0;  (d=a[k][k]) != 0. && k < n-1;  k++)   // Forward elimination

{

for (i = k+1;  i<n;  i++)

{

for (j = k+1, a[i][0] = c = a[i][k]/d;  j < n+1;  j++)

a[i][j] -= c * a[k][j];

}

progress = int(double(k) / n) * 100 - 20;

}

if (!d) // Bad matrix

{

error = new char[64];

sprintf (error, "\nZero Pivot at line: %d", k+1);

return false;

}

progress = 80;

for (k = n-1;  k >= 0;  --k)  // Backward substitution

{

for (s=0., j=n-1; j>k; --j)

s += a[k][j] * x[j];

x[k] = (a[k][n]-s) / a[k][k];

}

progress = 100;

return true;

}

//==== Экспортируемый класс

class __declspec(dllexport) Geometry

{

friend __declspec(dllexport) bool Solve (Geometry* p, double**& u, int ny, int nx);

private:

int nx, ny;

double

*b[8], // Boundary left, right, bottom, top

**py,     // Diagonal blocks (vertical nodes links)

**px,     // Diagonal blocks (horizontal nodes links)

**sr;     // Source matrix

void Init (int nx, int ny)

{

// 0, 1 - left,           2, 3 - right,  4, 5 - bottom,     6, 7 - top

for (int i=0; i<4; i++)

{

b[i] = new double [ny];   memset (b[i], 0, ny * sizeof(double));

b[i+4] = new double [nx]; memset (b[i+4], 0, nx * sizeof(double));

}

AllocMatrix (px, ny, nx);

AllocMatrix (py, ny, nx);

AllocMatrix (sr, ny, nx);

}

public:

Geometry () {}

Geometry (int nx, int ny) { Init (nx, ny); }

char* Say() { return "Yes, I'm alive and I'm here with you\n"; }

~Geometry ()

{

for (int i=0; i<8; i++)

delete [] b[i];

ClearMatrix (px, ny);

ClearMatrix (py, ny);

ClearMatrix (sr, ny);

}

};

//==== Экспортируемый метод, использующий экспортируемый  класс

Похожие материалы

Информация о работе