4. Создание
динамически присоединяемой библиотеки (DLL) в среде Microsoft Visual C++.
DLL (Dynamic Link Library) – это динамически присоединяемая библиотека. DLL, как и другие библиотеки, позволяют программисту достаточно просто распространять новые функции и другие ресурсы. DLL отличаются от других библиотек тем, что они присоединяются к приложению во время выполнения, а не в цикле компиляции. Этот процесс называют динамической компоновкой в противоположность статической компоновке. Статическая компоновка происходит в цикле компиляции, во время присоединения к приложению исполнительных библиотек С++. DLL в мультипрограммной среде имеют ещё то преимущество, что они позволяют приложениям разделять как функции, так и ресурсы.
Иcпользование DLL позволяет написать универсальный код модифицированного генетического алгоритма для целевых функций произвольного вида. DLL достаточно легко можно создать при помощи Microsoft Visual C++. Для его создания необходимо выполнить следующие действия.

Рис.1. Диалог New позволяет создать проект MFC AppWizard (dll)

Рис.2. На первом шаге необходимо выбрать опцию разделяемой MFC DLL
Когда AppWizard создаст базовый код для проекта Fitness , каталог Fitness будет содержать файлы, показанные на рис.3.

Рис.3. Левая панель показывает файлы, созданные AppWizard для проекта DLL Fitness
Заголовочный
файл Fitness.h
В заголовочном файле Fitness.h хранятся прототипы любых функций, которые необходимо экспортировать из DLL. Для того, чтобы создаваемую DLL можно было бы использовать, необходимо определить прототип функции цели с именем Fitness
Ниже представлен частичный листинг файла Fitness.h , где жирным шрифтом выделен добавленный прототип функции цели.
// Fitness.h : main header file for the FITNESS
DLL
//
.
.
.
#include "resource.h" // main symbols
_declspec( dllexport )
double WINAPI Fitness( const double *);
/////////////////////////////////////////////////////////////////////////////
// CFitnessApp
// See Fitness.cpp for the implementation of
this class
//
class CFitnessApp : public CWinApp
{
.
.
.
Microsoft использует расширенный синтаксис атрибутов, таких, как _declspec, для упрощения и стандартизации своих специфических расширений языка С++. Это ключевое слово указывает, что представитель данного типа будет храниться со специфичным для Microsoft атрибутом класса хранения.
Параметр double указывает тип данных, возвращаемый функцией.
Файл
исходного кода Fitness.cpp
Приведем несколько примеров функций, вставленных в созданный мастером AppWizard шаблон исходного кода. Следующий листинг показывает сделанные добавления. Они выделены жирным шрифтом
// Fitness.cpp : Defines the initialization
routines for the DLL.
//
#include "stdafx.h"
#include "Fitness.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFitnessApp
BEGIN_MESSAGE_MAP(CFitnessApp, CWinApp)
//{{AFX_MSG_MAP(CFitnessApp)
//
NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of
generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFitnessApp construction
CFitnessApp::CFitnessApp()
{
//
TODO: add construction code here,
//
Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CFitnessApp object
CFitnessApp theApp;
_declspec( dllexport )
double WINAPI Fitness(const double* dW)
{
double dKriteri=(sin(3.14*dW[0]) +
sin(3.14*dW[1]))*10 + 0.05*(dW[0] - 1.5*3.14)*(dW[0] - 1.5*3.14)*(dW[1] -
1.5*3.14)*(dW[1] - 1.5*3.14);
return dKriteri;
}
Здесь dW[2] – вектор настроечных коэффициентов.
// Fitness.cpp : Defines the initialization
routines for the DLL.
//
#include "stdafx.h"
#include "Fitness.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFitnessApp
BEGIN_MESSAGE_MAP(CFitnessApp, CWinApp)
//{{AFX_MSG_MAP(CFitnessApp)
//
NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of
generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFitnessApp construction
CFitnessApp::CFitnessApp()
{
//
TODO: add construction code here,
//
Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CFitnessApp object
CFitnessApp theApp;
_declspec( dllexport )
double WINAPI Fitness(const double* dW)
{
double dKriteri = 10;
// ВСПОМОГАТЕЛЬНЫЕ МАССИВЫ
double *x, *x1, *x2, *x3, *x4, *x5, *x6, *x7, *x8, *mu, *e, *I, *y1, *y2;
//ПАРАМЕТРЫ ОБЪЕКТА
РЕГУЛИРОВАНИЯ
double
m_dKob1,m_dKob2,m_dT1ob1,m_dT2ob1,m_dT1ob2,m_dT2ob2,m_dTau1, m_dTau2;
int m_nN, //Число
точек переходного процесса
m_dLambda, //Возмущение по каналу регулирующего органа
m_dU; //Возмущение
по каналу задания
double m_dDt; //шаг квантования по времени
m_nN = 3000;
m_dDt = 0.1;
y2
= new double [m_nN+1];
y1
= new double [m_nN+1];
x
= new double [m_nN+1];
x1
= new double [m_nN+1];
x2
= new double [m_nN+1];
x3
= new double [m_nN+1];
x4
= new double [m_nN+1];
x5
= new double [m_nN+1];
x6
= new double [m_nN+1];
x7 =
new double [m_nN+1];
x8
= new double [m_nN+1];
mu = new double [m_nN+1];
e =
new double [m_nN+1];
I =
new double [m_nN+1];
m_dKob1 = 0.08;
m_dKob2 = 0.1;
m_dT1ob1=54.7;
m_dT2ob1=9.1;
m_dT1ob2=48.9;
m_dT2ob2=11.5;
m_dTau1= 23;
m_dTau2=10;
int t1 =
static_cast<int>(m_dTau1/m_dDt);
int t2 =
static_cast<int>(m_dTau2/m_dDt);
double dImod1 = 0,
dImod2 = 0;
memset((void*)y1 , 0, sizeof(double)*m_nN);
memset((void*)y2 , 0, sizeof(double)*m_nN);
memset((void*)x , 0, sizeof(double)*m_nN);
memset((void*)x1 , 0,
sizeof(double)*m_nN);
memset((void*)x2 , 0,
sizeof(double)*m_nN);
memset((void*)x3 , 0,
sizeof(double)*m_nN);
memset((void*)x4 , 0,
sizeof(double)*m_nN);
memset((void*)x5 , 0,
sizeof(double)*m_nN);
memset((void*)x6 , 0,
sizeof(double)*m_nN);
memset((void*)x7 , 0,
sizeof(double)*m_nN);
memset((void*)x8 , 0,
sizeof(double)*m_nN);
memset((void*)mu, 0, sizeof(double)*m_nN);
memset((void*)e , 0, sizeof(double)*m_nN);
memset((void*)I , 0, sizeof(double)*m_nN);
for(int j=0; j<2;j++)
{
if(j==0)
{
m_dLambda =1;
m_dU = 0;
}
if(j==1)
{
m_dLambda =0;
m_dU = 1;
}
for(int i=0; i<m_nN;i++)
{
x[i+1] = m_dLambda + mu[i];
x1[i+1] =
(( m_dDt*i )<m_dTau1) ? 0 : x[ i- t1 ] ;
x2[i+1] =
(1-m_dDt/m_dT1ob1)*x2[i] + m_dKob1*x1[i]*(m_dDt/m_dT1ob1) ;
x3[i+1] =
(1-m_dDt/m_dT2ob1)*x3[i] + 1*x2[i]*(m_dDt/m_dT2ob1) ;
x4[i+1] =
(( m_dDt*i )<m_dTau2) ? 0 : x[ i- t2 ] ;
x5[i+1] =
(1-m_dDt/m_dT1ob2)*x5[i] + m_dKob2*x4[i]*(m_dDt/m_dT1ob2) ;
x6[i+1] =
(1-m_dDt/m_dT2ob2)*x6[i] + 1*x5[i]*(m_dDt/m_dT2ob2) ;
x7[i+1] =
(1-m_dDt/dW[3])*x7[i] + dW[2]*x6[i]*(m_dDt/dW[3]) ;
x8[i+1] =
dW[2]*x6[i+1]-x7[i+1];
e[i+1]
= m_dU - x3[i] - x8[i];
I[i+1] = I[i] + dW[1]*e[i]*m_dDt;
mu[i+1] = dW[0]*e[i+1] + I[i+1];
if(mu[i+1] > 10000) mu[i+1] = 10000;
if(mu[i+1] < -10000) mu[i+1] = -10000;
if(m_dU !=0)
{
dImod2 += fabs(1-x3[i]);
}
else
{
dImod1 += fabs(x3[i]);
}
}//for
}//for
delete
[]y1;
delete
[]y2;
delete
[]x;
delete
[]x1;
delete
[]x2;
delete
[]x3;
delete
[]x4;
delete
[]x5;
delete
[]x6;
delete
[]x7;
delete
[]x8;
delete[] mu;
delete[] e ;
delete[] I ;
dKriteri = 100*dImod1*m_dDt +
dImod2*m_dDt; //Возвращаем суммарный интеграл по модулю при возмущениях
//
m_dLambda =1; m_dU = 0 и m_dLambda =0; m_dU = 1
return dKriteri;
}
Здесь dW[4]- вектор настроечных коэффициентов.
Для компиляции библиотеки
необходимо нажать клавишу F7
или выбрать в меню Build->Build