4. Создание динамически присоединяемой библиотеки (DLL) в среде Microsoft Visual C++.

 

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

 

Иcпользование DLL позволяет написать универсальный код модифицированного генетического алгоритма для целевых функций произвольного вида.  DLL достаточно легко можно создать при помощи Microsoft Visual C++. Для его создания необходимо выполнить следующие  действия.

  1. Выбрать в меню Visual C++ File -> New (рис.1)

 

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

 

  1. Назвать новый проект MFC AppWizard (dll)  Fitness.
  2. Нажать ОК, чтобы запустить MFC AppWizard.
  3. В диалоге Step 1 выбрать опцию Regular DLL using shared MFC DLL (рис. 2)

 

Рис.2. На первом шаге необходимо выбрать опцию разделяемой MFC DLL

 

  1. В диалогах всех остальных шагов необходимо оставить установки по умолчанию, предлагаемые мастером AppWizard.
  2. Нажать Finish.

 

Когда 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 шаблон исходного кода. Следующий листинг показывает сделанные добавления. Они выделены жирным шрифтом

 

  1. Функция

 

// 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] – вектор настроечных коэффициентов.

 

  1. Переходный процесс в автоматической системе регулирования с дифференциатором (для температуры перегретого пара котла).

 

// 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

Используются технологии uCoz