современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран
Скачать 2.24 Mb.
|
12.4. Идентификация объекта Идентификация объекта ActiveX выполняется по глобальному уникальному идентификатору GUID (globally unique identifier), определенному в файле dfwinty.f90: 379 О. В. Бартеньев. Современный ФОРТРАН type guid sequence integer*4 data1 integer*2 data2 integer*2 data3 character*8 data4 end type guid COM использует GUID для идентификации классов, интерфейсов и других требующих уникальных идентификаторов характеристик объекта. Чтобы создать экземпляр объекта, необходимо сообщить СОМ его (объекта) GUID. Также COM поддерживает программный идентификатор ProgID(programmatic identifier), имеющий вид: application_name.object_name.object_version Например: Excel.Application.8. Тип ProgID - CHARACTER(*). Соответствие между программным идентификатором и идентификатором класса устанавливается подпрограммой COMCLSIDFromProgID. 12.5. Примеры работы с данными Автоматизации С Автоматизацией связаны специальные виды данных, например разнообразные константы, BSTR-строки, OLE-массивы или варианты, и процедуры, выполняющие с ними определенные действия, например размещение данных в памяти, изменение их значений или преобразование типов. В CVF эти данные определены в файле dfwinty.f90, а интерфейсы связанных с ними процедур - в файле oleaut32.f90. Собственно процедуры реализованы в файле oleaut32.dll. Для детального ознакомления с видами данных Автоматизации можно рекомендовать, например, приведенную в разд. 12.2 литературу. Здесь же приведем понятия OLE-массивов, BSTR-строк и вариантов, перечислим процедуры, работающие с этими объектами, и дадим ряд примеров. Заметим, что приводимые далее процедуры описаны также и в поставляемом с CVF файлом помощи. Навыки работы с данными Автоматизации нужны программисту, использующему COM-технологии, в частности, для того, чтобы обеспечить обмен данными между процедурами Фортрана и Автоматизации. При этом потребуется выполнять операции по преобразованию типов, например переходить от строки Фортрана к BSTR-строке, и данных, например передавать данные из массива Фортрана в OLE-массив. 12.5.1. OLE-массивы Массивы, связанные с диспетчерским интерфейсом IDispatch, называются OLE-массивами. Их другое название - безопасные массивы. Внутри OLE-массива содержится информация о его ранге и форме. Для доступа к массиву используется его дескриптор, возвращаемый функцией 380 12. Конструктор модулей для объектов ActiveX SafeArrayCreate . Данные массива размещаются в памяти так же, как и данные массива Фортрана: быстрее всего изменяется самый первый индекс. В частности, в случае двумерного OLE-массива его данные размещаются в памяти компьютера по столбцам. С OLE-массивами связаны приведенные в табл. 12.3 функции. Все они имеют тип INTEGER(4). Таблица 12.3. Функции, работающие с OLE-массивами Функция Назначение SafeArrayAccessData Увеличивает счетчик блокировок массива и возвращает указатель на данные массива SafeArrayAllocData Выделяет память для OLE-массива, используя дескриптор, возвращенный SafeArrayAllocDescriptor SafeArrayAllocDescriptor Выделяет память для дескриптора массива SafeArrayCopy Копирует массив SafeArrayCopyData Копирует исходный массив в другой, предварительно освободив содержимое последнего SafeArrayCreate Создает новый дескриптор массива SafeArrayCreateVector Создает вектор заданного размера SafeArrayDestroy Разрушает дескриптор массива SafeArrayDestroyData Освобождает память, занятую массивом SafeArrayDestroyDescriptor Освобождает память, занятую дескриптором массива SafeArrayGetDim Возвращает ранг массива SafeArrayGetElement Возвращает элемент массива SafeArrayGetElemsize Возвращает размер элемента массива в байтах SafeArrayGetLBound Возвращает нижнюю границу для заданного измерения SafeArrayGetUBound Возвращает верхнюю границу для заданного измерения SafeArrayLock Увеличивает число блокировок массива SafeArrayPtrOfIndex Возвращает указатель на элемент массива SafeArrayPutElement Присваивает значение элементу массива SafeArrayRedim Изменяет правую, менее значимую границу массива SafeArrayUnaccessData Уменьшает счетчик блокировок массива и делает недействительным указатель, возвращенный SafeArrayAccessData SafeArrayUnlock Уменьшает счетчик блокировок массива 381 О. В. Бартеньев. Современный ФОРТРАН Пример. Первоначально создается OLE-массив, по форме совпадающий с массивом Фортрана a, затем данные из массива a переносятся в OLE- массив, после чего его содержимое отображается на экране. program SafeArrayTest use dfcomty ! Модуль ссылается на DFWINTY use dfcom ! Модуль ссылается на OLEAUT32 и DFWINTY implicit none integer(4) :: result, i, j, value integer(4) :: a(4, 3) ! Массив Фортрана type(sa_bounds) :: ab(2) ! Тип sa_bounds описан в модуле DFWINTY integer(4) :: indices(2) integer(4) :: safeArray ! OLE-массив ! Задание массива по столбцам a = reshape((/ 11, 12, 13, 14, & ! Столбец 1 21, 22, 23, 24, & ! Столбец 2 31, 32, 33, 34 /), shape = (/ 4, 3 /)) ! Столбец 3 ! Формируем OLE-массив ab(1)%lbound = 1 ! Нижняя граница по первому измерению ab(1)%extent = ubound(a, 1) ! Протяженность по первому измерению ab(2)%lbound = 1 ab(2)%extent = ubound(a, 2) ! Создаем новый дескриптор массива ! Константа VT_I4 описана в файле dfwinty.f90 ! Она означает, что OLE-массив содержит 4-байтовые целые числа safeArray = SafeArrayCreate(VT_I4, 2, ab(1)) ! Интерфейсы функций, работающих с OLE-массивами, см. в oleaut32.f90 do j = ab(2)%lbound, ab(2)%extent ! Переносим данные в OLE-массив do i = ab(1)%lbound, ab(1)%extent indices(1) = i; indices(2) = j ! Переносим данные из массива Фортрана в OLE-массив result = SafeArrayPutElement(safeArray, indices(1), loc(a(i, j))) end do end do do j = ab(2)%lbound, ab(2)%extent ! Читаем и выводим данные OLE-массива do i = ab(1)%lbound, ab(1)%extent indices(1) = i; indices(2) = j result = SafeArrayGetElement(safeArray, indices(1), loc(value)) write(*, '(i5)', advance = 'no') value ! Вывод без продвижения end do print * ! Переход на новую строку end do result = SafeArrayDestroy(safeArray) ! Освобождаем память end program SafeArrayTest 382 12. Конструктор модулей для объектов ActiveX Замечание. В модуле OLEAUT32 интерфейсы определены не для всех функций табл. 12.3. Однако при необходимости недостающий интерфейс можно записать самостоятельно. Пример. В программе OLE_vector создается интерфейс функции SafeArrayCreateVector, которая используется для формирования OLE- вектора. В вектор заносятся элементы строки string. program OLE_vector use dfwinty ! Для получения значения VT_UI1 use dfcom implicit none ! Опишем интерфейс SafeArrayCreateVector, поскольку его нет в модуле OLEAUT32 interface integer(4) function SafeArrayCreateVector(vt, lLbound, cElements) !dec$ attributes default, stdcall, alias : & '_SafeArrayCreateVector@' :: SafeArrayCreateVector !dec$ attributes value :: vt ! Все параметры передаются по значению !dec$ attributes value :: lLbound !dec$ attributes value :: cElements integer(4), intent(in) :: vt, lLbound , cElements end function SafeArrayCreateVector end interface integer(4) :: safeArray, len, i, indices(1), result character(30) :: string = 'Test string' character(1) :: ch len = len_trim(string) ! Длина строки string без завершающих пробелов ! Создаем новый дескриптор массива ! Константа VT_UI1 описана в файле dfwinty.f90 ! Она означает, что OLE-массив содержит символы safeArray = SafeArrayCreateVector(VT_UI1, 1, len) do i = 1, len ! Заносим данные в OLE-вектор indices(1) = i result = SafeArrayPutElement(safeArray, indices(1), loc(string(i:i))) end do do i = 1, len ! Контрольный вывод indices(1) = i ! Читаем и выводим данные из OLE-вектора result = SafeArrayGetElement(safeArray, indices(1), loc(ch)) write(*, '(a)', advance = 'no') ch ! Вывод без продвижения end do print * ! Переход на новую строку end program OLE_vector 12.5.2. BSTR-строки Строки, относящиеся к типам и структурам данных интерфейса IDis- patch, называются BSTR-строками. Эти строки завершаются нулевым символом (null) и предваряются целым числом, хранящим их длину. Внутри 383 О. В. Бартеньев. Современный ФОРТРАН строки также могут быть нулевые символы. Фактически BSTR - это указатель на строку. Его тип в Фортране - INTEGER(4). С BSTR-строками связаны приведенные в табл. 12.4 процедуры. Все они, кроме подпрограммы SysFreeString, являются функциями типа INTE- GER(4). Таблица 12.4. Процедуры для BSTR-строк Функция Назначение SysAllocString Размещает новую строку и копирует в нее строку-параметр SysAllocStringByteLen Принимает ANSI-строку и возвращает BSTR, эту строку содержащий SysAllocStringLen Размещает новую строку заданной длины и копирует в нее соответствующее число символов из строки-параметра SysFreeString (подпрограмма) Освобождает ранее размещенную строку SysReAllocString Изменяет размещение строки, копируя в нее передаваемые данные SysReAllocStringLen Изменяет размещение строки, копируя в нее заданное число символов SysStringByteLen Возвращает длину строки в байтах SysStringLen Возвращает длину строки VectorFromBSTR Возвращает OLE-вектор, каждый элемент которого равен соответствующему символу BSTR-строки BSTRFromVector Возвращает BSTR-строку, каждый символ которой равен соответствующему элементу OLE-вектора Замечания: 1. Модуль DFCOM, размещенный в файле dfcom.f90, содержит функцию ConvertStringToBSTR, преобразовывающую строку Фортрана в BSTR, и функцию ConvertBSTRToString, выполняющую обратные преобразования. 2. В модуле OLEAUT32 отсутствуют интерфейсы функций SysAllocString- ByteLen, VectorFromBSTR и BSTRFromVector. Пример. Формируется BSTR-строка, содержащая текст Test string. Далее она преобразовывается в строку Фортрана. program BSTR_example use dfcom integer(4) :: bstr, len character(30) :: string = 'Test string', string2 = ' ' bstr = ConvertStringToBSTR(string) ! Формируем BSTR-строку с текстом Test string ! Преобразовываем BSTR-строку в строку Фортрана 384 12. Конструктор модулей для объектов ActiveX len = ConvertBSTRToString(bstr, string2) print *, string2 ! Test string end program BSTR_example 12.5.3. Варианты Производный тип данных variant определен в файле dfwinty.f90: type variant sequence integer(2) vt integer(2) reserved1, reserved2, reserved3 record /variant_union/ vu end type variant Структура variant_union, использованная при формировании типа variant, имеет вид: structure /variant_union/ ! Взята из файла dfwinty.f90 union map integer(4) long_val ! VT_I4 end map map character char_val ! VT_UI1 end map map integer(2) short_val ! VT_I2 end map map real(4) float_val ! VT_R4 end map map real(8) double_val ! VT_R8 end map map integer(2) bool_val ! VT_BOOL end map map integer(4) scode_val ! VT_ERROR end map map real(8) date_val ! VT_DATE end map map ! ptr_val - целочисленный указатель integer(4) ptr_val ! Для параметров, передаваемых по ссылке end map end union end structure 385 О. В. Бартеньев. Современный ФОРТРАН Тип variant широко распространен в Автоматизации; им, в частности, обладает подавляющее большинство параметров свойств и методов Автоматизации. Переменные типов variant называются вариантами. Варианты предназначаются для хранения данных разных типов и позволяют преобразовывать один тип в другой. Возможные типы, используемые с вариантами и другими объектами Автоматизации, задаются определенными в модуле DFWINTY целочисленными константами. Перечислим некоторые из них: integer(2), parameter :: vt_empty = 0 ! Значение не задано integer(2), parameter :: vt_null = 1 ! null integer(2), parameter :: vt_i2 = 2 ! INTEGER(2) integer(2), parameter :: vt_i4 = 3 ! INTEGER(4) integer(2), parameter :: vt_r4 = 4 ! REAL(4) integer(2), parameter :: vt_r8 = 5 ! REAL(8) ! Дата - число с плавающей точкой двойной точности integer(2), parameter :: vt_date = 7 integer(2), parameter :: vt_bstr = 8 ! BSTR ! Указатель на объект, реализующий IDispatch integer(2), parameter :: vt_dispatch = 9 integer(2), parameter :: vt_error = 10 ! Код ошибки integer(2), parameter :: vt_bool = 11 ! Истина (#FFFF) или ложь (#0000) integer(2), parameter :: vt_variant = 12 ! Указатель на вариант ! Указатель на объект, реализующий Iunknown integer(2), parameter :: vt_unknown = 13 integer(2), parameter :: vt_i1 = 16 ! INTEGER(1) integer(2), parameter :: vt_ui1 = 17 ! Целое без знака длиной в 1 байт integer(2), parameter :: vt_ui2 = 18 ! Целое без знака длиной в 2 байта integer(2), parameter :: vt_ui4 = 19 ! Целое без знака длиной в 4 байта Манипулировать вариантами позволяют приведенные в табл. 12.5 функции и подпрограмма. Тип функций - INTEGER(4). Таблица 12.5. Процедуры для вариантов Функция Назначение VariantChangeType Преобразовывает вариант в другой тип VariantChangeTypeEx Преобразовывает вариант в другой тип, используя идентификатор местности LCID, употребляемый при работе с разноязычными приложениями VariantClear Очищает вариант (освобождает память, занимаемую вариантом) VariantCopy Копирует вариант VariantCopyInd Копирует вариант, выполняя преобразование флага VT_BYREF, обеспечивающего передачу по ссылке, в BYVAL, что гарантирует передачу варианта по 386 12. Конструктор модулей для объектов ActiveX значению VariantInit (подпрограмма) Выполняет инициализацию варианта VariantTimeToDosDateTime Преобразовывает время, представленное в виде варианта, в дату и время в формате MSDOS VariantTimeToSystemTime Преобразовывает время, представленное в виде варианта, в системное представление времени Замечание. Модуль OLEAUT32 не содержит интерфейсы функция Variant- TimeToDosDateTime и VariantTimeToSystemTime. Пример. Создаются два варианта. Первый предназначается для хранения указателя BSTR, а второй - для 4-байтового вещественного числа. Каждый вариант получает соответствующее значение: первый - указатель на BSTR- строку "Компак Фортран", второй - число 6.1. Далее второй вариант преобразовывается в тип BSTR; оба варианта переводятся в строки Фортрана и выводится результат. program variant_example use dfcomty use dfcom use TextTransfer ! Для вывода русского текста в DOS-окно integer(4) :: status, length ! Код модуля TextTransfer см. в прил. 1 character(80) :: char1, char2 type(variant) v1, v2 ! Тип variant описан в файле dfwinty.f90 call VariantInit(v1) ! Инициализация вариантов call VariantInit(v2) v1%vt = VT_BSTR ! Вариант v1 хранит BSTR-строку ! Преобразовываем строку Фортрана в строку BSTR ! Преобразовывающую функцию ConvertStringToBSTR см. в файле dfcom.f90 v1%vu%ptr_val = ConvertStringToBSTR("Компак Фортран") v2%vt = VT_R4 ! 4-байтовое вещественное число v2%vu%float_val = 6.1 ! Интерфейсы функций, работающих с вариантами, см. в oleaut32.f90 ! Преобразовываем вариант v2 в BSTR-строку status = VariantChangeType(v2, v2, 0, VT_BSTR) ! Преобразовываем строки BSTR в строки Фортрана ! Преобразовывающую функцию ConvertBSTRToString см. в файле dfcom.f90 length = ConvertBSTRToString(v1%vu%ptr_val, char1) length = ConvertBSTRToString(v2%vu%ptr_val, char2) print *, trim(RuDosWin(trim(char1) // " " // trim(char2), .false.)) status = VariantClear(v1) ! Очищаем вариант status = VariantClear(v2) end program variant_example 387 О. В. Бартеньев. Современный ФОРТРАН 12.6. Другие источники информации Технология взаимодействия с помощью СОМ, включающая в том числе и OLE-автоматизацию, подробно описана, кроме [14], в следующих источниках: • How OLE and COM Solve the Problems of Component Software Design/by K. Brockschmidt//Microsoft Systems Journal. 1996. Vol. 11, N 5 (May). Р. 63-80. • Inside OLE/Red. by K. Brockschmidt. 2d ed. Redmond; Washington: Micro- soft Press, 1995. • OLE 2 Programmer's Reference, Vol. 2. Redmond; Washington: Microsoft Press, 1994. • Understanding ActiveX and OLE/Red. by D. Chappell. Redmond; Washing- ton: Microsoft Press, 1996. • Win 32 SDK, OLE Programmer's Reference online version. • Win 32 SDK, Automation online version. • http://mspress.microsoft.com/. 12.7. Как воспользоваться объектом ActiveX Чтобы использовать объект ActiveX в Фортран-программе, необходимо выполнить следующие действия: • найти существующий или установить новый объект в системе. Объект можно зарегистрировать специальной программой либо в результате его создания средствами Visual C++ или Visual Basic (см., например, документацию по DS); • определить вид интерфейса, который объект имеет (в общем случае объект может иметь несколько интерфейсов), и используемые в объекте типы данных. Необходимые об объекте сведения добываются из связанной с ним документации. Также их можно получить, воспользовавшись имеющимся в DS средством просмотра объектов Автоматизации, вызов которого происходит в результате выполнения цепочки Tools - OLE/COM Object Viewer; • применить КМ и получить код модуля, обеспечивающего доступ к объекту; • написать программу на Фортране, в которой есть ссылки на полученный модуль и вызовы необходимых для работы с объектом процедур. 12.8. Применение конструктора модулей Вызов КМ обеспечивает цепочка Tools - Fortran Module Wizard. После ее выполнения в появившемся окне (рис. 12.1) необходимо задать источник, из которого КМ получит данные об объекте. |