Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 50092.doc
Скачиваний:
17
Добавлен:
30.04.2022
Размер:
4.95 Mб
Скачать

1. Создание проектов прикладных библиотек

КОМПАС В СРЕДЕ VISUAL C++

Создать прикладную библиотеку и подготовить ее к работе в системах КОМПАС, старше V10, можно двумя способами: воспользоваться мастером создания библиотек Visual C++ 6.0 или изменить имеющиеся в директории «..\SDK\C++\ Visualc» рабочие проекты прикладных библиотек.

Создание шаблона библиотеки при помощи мастера создания библиотек (Wizard), разработанного специалистами системы КОМПАС, производится легко - достаточно следовать инструкциям разработчика. Для подключения мастера создания библиотек необходимо скопировать файл LibraryWizard.awx в директорию «C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Template» или в папку Template аналогичной директории куда установлен MS Visual C++ 6.0.

После подключения мастера создания библиотек в окне нового проекта появиться новый пункт LibraryWizard. Пути к заголовкам библиотек (Include директориям) в опциях нового проекта по умолчанию настроены для папки «..\SDK\C++\Visualc», поэтому при создании проекта необходимо указать этот путь в location, как показано на рисунке 1.

Рис. 1. Мастер создания прикладных библиотек системы КОМПАС в Visual C++ 6.0

Используя опции генератора данных, мастер подготовит проект подключаемой для системы КОМПАС динамической библиотеки в среде Visual С++.

Пример кода на Visual С++ динамически подключаемой прикладной библиотеки с именем my_first_library представлен на листинге:

// My_first_library.cpp - Библиотека на Visual C++

#include "stdafx.h"

#include <afxdllx.h>

#include "my_first_library.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

// Специальная структура, используемая для инициализации DLL

// ---

static AFX_EXTENSION_MODULE My_first_libraryDLL = { NULL, NULL };

HINSTANCE g_hInstance = NULL;

IApplicationPtr newKompasAPI( NULL );

void OnProcessDetach();// Отключение библиотеки

// Стандартная точка входа

// Инициализация и завершение DLL

// ---

extern "C" int APIENTRY

DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

{

g_hInstance = hInstance;

if (dwReason == DLL_PROCESS_ATTACH)

{

TRACE0("MY_FIRST_LIBRARY.AWX Initializing!\n");

AfxInitExtensionModule(My_first_libraryDLL, hInstance);

new CDynLinkLibrary(My_first_libraryDLL);

}

else if (dwReason == DLL_PROCESS_DETACH)

{

TRACE0("MY_FIRST_LIBRARY.AWX Terminating!\n");

OnProcessDetach();

AfxTermExtensionModule(My_first_libraryDLL);

}

return 1; // ok

}

// Получить доступ к API

void GetNewKompasAPI()

{

if ( !( IApplication * )newKompasAPI )

{ CString filename;

if( ::GetModuleFileName(NULL, filename.GetBuffer(255), 255) )

{

filename.ReleaseBuffer( 255 );

CString libname;

libname = LoadStr( IDR_API7 ); // kAPI7.dll

filename.Replace( filename.Right(filename.GetLength() - (filename.ReverseFind('\\') + 1)),

libname );

HINSTANCE hAppAuto = LoadLibrary( filename ); // идентификатор kAPI7.dll

if( hAppAuto )

{

// Указатель на функцию возвращающую интерфейс KompasApplication

typedef LPDISPATCH ( WINAPI * FCreateKompasApplication )();

FCreateKompasApplication pCreateKompasApplication =

(FCreateKompasApplication)GetProcAddress( hAppAuto, "CreateKompasApplication" );

if ( pCreateKompasApplication )

newKompasAPI = IDispatchPtr ( pCreateKompasApplication(), false ); // Получаем интерфейс Application

FreeLibrary( hAppAuto );

}}}}

// Задать идентификатор ресурсов

unsigned int WINAPI LIBRARYID()

{return IDR_LIBID;}

// Головная функция библиотеки

void WINAPI LIBRARYENTRY( unsigned int comm )

{ switch ( comm )

{

case 1:

{

// Выдача сообщения пользователю

MessageT( _T("Успешный запуск прикладной библиотеки!") );

break;

}}}

// Завершение приложения

void OnProcessDetach()

{

newKompasAPI = NULL;

}

// Загрузить строку из ресурса

CString LoadStr( int strID )

{ TCHAR temp[_MAX_PATH];

LoadString( My_first_libraryDLL.hModule, strID, temp, _MAX_PATH );

return temp;

}

А

library Vtulka;

uses

SysUtils,

Classes,

Forms,

Unit1 in 'Unit1.pas' {Form1};

{$E rtw}

{$R *.res}

procedure Initialize();

begin

try

if Application = nil then

// Если объект приложение удалён, то создаём заново

Application := TApplication.Create(nil);

if Application <> nil then

begin

// Поизводим его инициализацию

Application.Initialize;

// Создаём форму

Application.CreateForm(TForm1, Form1);

// Запускаем приложение

Application.Run;

// После завершения работы приложения освобождаем

Application.Free();

Application := nil;

end;

except

if Application <> nil then

begin

// Если есть исключения, то завершаем приложение

Application.Terminate;

Application.Free();

Application := nil;

end;

end;

end;

(*****************************************************)

function LibraryName(): PChar; pascal;

begin

// Возвращаем имя приложения

Result := PChar('Штуцер');

end;

(*****************************************************)

налогичный код на Delphi приведен в следующем листинге:

function LibraryId(): LongWord; pascal;

begin

// Возвращаем идентификатор библиотеки

Result := 1000;

end;

(*****************************************************)

procedure LibraryEntry(command: WORD); pascal;

begin

// При вызове входной функции инициализируем приложение

Initialize();

end;

(*****************************************************)

exports

LibraryName name 'LIBRARYNAME',

LibraryId name 'LIBRARYID',

LibraryEntry name 'LIBRARYENTRY';

begin

end.

Для успешной компиляции и создания рабочего модуля библиотеки необходимо в файле «StdAfx.h» указать путь к директории, в которой находятся требуемые для успешной сборки проекта файлы (выделены жирным шрифтом). В среде разработки подключить заголовки (headers) c системными библиотеками (lib) SDK -в Visual C++6.0 «Tools->Options->Directories» и в разделе «Show directories for: Include files (Library files)» указать путь к соответствующим файлам, как показано на рисунке 2.

#if !defined(AFX_STDAFX_H__6D497DCE_3F78_47BD_915C_D3B34AF32D89__INCLUDED_)

#define AFX_STDAFX_H__6D497DCE_3F78_47BD_915C_D3B34AF32D89__INCLUDED_

#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers

#include <afxwin.h> // MFC core and standard components

#include <afxext.h> // MFC extensions

#include <afxcmn.h> // MFC support for Windows 95 Common Controls

#include <COMUTIL.H>

#include <comdef.h>

#pragma warning( disable : 4192 )

#include <libtool.h>

#include <LHead3d.h>

#import "g:\works2010\SDK\lib\ksConstants3D.tlb" no_namespace named_guids

#import "g:\works2010\SDK\lib\ksConstants.tlb" no_namespace named_guids

#import "g:\works2010\SDK\lib\kAPI2D5COM.tlb" no_namespace named_guids

#import "g:\works2010\SDK\lib\kAPI3D5COM.tlb" no_namespace named_guids

#import "g:\works2010\SDK\lib\kAPI7.tlb" no_namespace named_guids

#pragma warning( once : 4192 )

#endif // !defined(AFX_STDAFX_H__6D497DCE_3F78_47BD_915C_D3B34AF32D89__INCLUDED_)

Рис. 2. Подключение заголовков и прикладных библиотек системы КОМПАС в Visual C++

При «ручном» способе разработки прикладных библиотек может потребоваться внесение некоторых модулей из папки «..SDK\Lib» непосредственно в дерево построения проекта (WorkSpace) (рисунок 3). При сборке библиотеки имеется возможность воспользоваться опциями управления проекта (Project->Settings->C++&Links& Resources) для изменения производительности программного кода, обеспечения его компактности, включения в раздел ресурсов национальной таблицы символов, отличных от латинских, изменение имени конечного файла (рисунок 4). При окончательной сборке библиотеки необходимо поменять в опции «Активная конфигурация» режим «Debug» на «Release»-это действие приведет к уменьшению объема выходного файла динамически подключаемого приложения за счет удаления отладочной информации о проекте (Build->Set Active Configuration).

Рис. 3. Включение в проект файлов kAPI2D5.lib и kAPI3D5.lib для работы с чертежами и моделями

Рис. 4. Настройки проекта: изменение имени файла прикладной библиотеки

Полученный шаблон прикладной библиотеки достаточно просто перенести на другие среды разработки компании Microsoft-так, например, в версии Visual Studio 2010. NET необходимо переоткрыть проект, войти в раздел Property Manager (Менеджер разработки текущего проекта) и явным образом задать пути к папкам API SDK, содержащие разделы с lib (библиотеки разработки) и include (заголовки исполняемых функций) файлами. Все вышеописанные действия представлены на рисунке 5.

Рис. 5. Сборка проекта в Visual Studio2010.

Из приведенного выше примера большая часть кода представлена системным механизмом проектирования приложений, в котором реализованы общие принципы построения динамически подключаемых библиотек посредством технологии СОМ - наиболее широко используемой объектной модели для разработки рассредоточенных и действующих одновременно систем.

Термин "СОМ" представляет собой сокращение фразы Competent Object Model - компонентная объектная модель. Основой указанной технологии является некотороя особенность, состоящая в том, что программы строятся из блоков, которые, в свою очередь, состоят из объектов. Само по себе это обстоятельство не является нововедением в области программостроения - модульная архитектура и объектно-ориентированный подход к построению программ являются признанными стандартами достаточно давно. Особенностью является то, что представляют собой данные компоненты и объекты – в качестве блоков выступает непосредственно исполняемый двоичный код. Не "включаемые исходные тексты" компилируемые совместно с проектом, не "библиотеки стандартных программ", присоединяемые линкером, а непосредственно исполняемые файлы, которые никак не надо "связывать" со своим проектом - их достаточно зарегистрировать в операционной системе и они будут доступны любой программе исполняющейся на данной машине. Т.е. их использование в своей программе производится "без использования операций сборки модуля". Такая технология не является новой и называется "динамическая загрузка", она давно известна и её преимущества очевидны. А модули, которые позволяют загружать себя таким образом, называются динамически подключаемыми библиотеками (DLL). И в системе, Windows такая технология известна с момента ее создания. DLL и есть тот самый "двоичный исполняемый модуль", который может быть присоединен к программе лишь на стадии её выполнения. Однако, если просто весь проект распределить по нескольким динамическим библиотекам, то "двоичные компоненты" не получатся потому что, важнейший признак "компонентности" уже появится - исполняемую программу можно будет собирать из отдельных частей без операций сборки модуля. Но вот DLL - не компонента, DLL есть так называемое место нахождения компонент, используемых в программе. Из программы вызываются вполне конкретные процедуры и функции, которые только расположены в DLL. Кроме того, вызовы процедур "из своего модуля" и "из DLL" - не одинаковые действия. Вызов процедуры, которая располагается внутри "своего" модуля требует знания только имени этой процедуры, а если процедура располагается в DLL, то нужно знать ещё и имя самой библиотеки. Модель же COM позволяет этого "не знать", т.е. вызов объектов COM из своей программы осуществляется без знания того, где они расположены. Достаточно знать имя объекта. Другое отличие COM, уже от привычных объектов в стиле объектно-ориентированного программирования (ООП), состоит в том, что объекты ООП известны только компилятору. Это - абстракции, в которых работает программист и которые компилятор превращает в двоичные структуры "данные + код". Объекты ООП существующие в разных единицах компиляции и, тем более, помещенные в разные двоичные модули, ничего не могут друг о друге "знать" просто потому, что их там нет и никогда не было. Не случайно заголовочные файлы, содержащие описания всех объектов проекта, подаются на вход именно компилятора - потом они уже никому не нужны. Объекты же COM - действительно существуют в двоичном виде как объекты. И в таком качестве “известны” всем приложениям, которым необходим доступ к элементам этих объектов.

Возвращаясь к процессу проектирования библиотек, рассмотрим некоторые элементы программного кода на языке С++. В простейшем варианте в прикладной библиотеке содержится одна базовая функция, представленная на листинге ниже и выводящая сообщение на экран.

void WINAPI LIBRARYENTRY( unsigned int comm )

{ switch ( comm )

{

case 1:

{

//Выдача сообщения пользователю

MessageT( _T("Тестовая команда 1") );break;

}

}

}

В функцию WINAPI LIBRARYENTRY включен множественный оператор выбора switch(), по которому можно организовать вызов отдельного набора команд, составленных на языке С++ и API системы КОМПАС, функций, членов классов, структур, шаблонов, добавление в библиотеку вставок текста на языке ассемблера и т.д.

Листинг основной функции по расчету факториала, написанной на языке ассемблера:

void WINAPI LIBRARYENTRY( unsigned int comm )

{ TCHAR buf [255];

WORD iii;

__asm

{ mov ax,1

xor bx,bx

mov cx,8

label1:

inc bx

mul bx

loop label1

mov iii,ax };

_stprintf( buf, _T("Factorial = %d"), iii );

MessageT( buf );

}

Сообщение выводится на экран по команде «MessageT(buf);», где каждый символ представлен двухбайтовым значением и соответствует национальной таблице символов в Unicode. Использование Unicode требует коррекции функций и типов переменных как минимум в функциях, использующих MFC.

Строковые константы в коде необходимо окружить дефайном

_T, например: «char str[100]=“”;» заменяется на «TCHAR str[100]=_T(“”);». Таким образом, проект можно будет компилировать под Компас 10 в Unicode. В случае разработки библиотек под систему Компас 9 надо переключиться на неюникодную конфигурацию.

Потребуется замена вызова неюникодных функций, работающих со строками на объявления, которые в зависимости от типа компиляции заменяются на юникодный или неюникодный аналог функции. Например: strcmp strcpy atof. Данные функции в местах, где будет использоваться TCHAR*, надо заменить объявлениями из файла TCHAR.h. Примеры замен необходимо уточнить в документации.

Вывод текстовых сообщений может быть выполнен не только с помощью специфического API КОМПАС, но и средствами разработки WinAPI, MFC, которые реализованы в интегрированной среде Visual C++:

Пример:

MessageBox(NULL,_T("Сообщение"),_T("Пример вывода"),MB_OK);

AfxMessageBox(_T("Сообщение"),MB_ICONINFORMATION ,0);

Для того чтобы перевести листинг программы в машинный код, необходимо выполнить компиляцию проекта, выбрав опцию «Build» в меню интегрированной среды, или нажать функциональную клавишу F7. Полученный файл с расширением .rtw можно подключить в окне менеджера библиотек Компас путем добавления описания прикладной библиотеки, как показано на рисунке 6.

Рис. 6. Подключение разработанной прикладной библиотеки в окне менеджера библиотек Компас

Результаты спроектированной библиотеки в Visual Studio 2010 представлены на рисунке 7, когда модуль уже подключен к менеджеру библиотек в Компас V12.

Рис. 7. Вывод сообщения средствами спроектированной прикладной библиотеки