Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

О. В. Бартеньев. Современный ФОРТРАН

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

! Длина строки string без завершающих пробелов

len = len_trim(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-строки

Строки, относящиеся к типам и структурам данных интерфейса IDispatch, называются BSTR-строками. Эти строки завершаются нулевым символом (null) и предваряются целым числом, хранящим их длину. Внутри

383

О. В. Бартеньев. Современный ФОРТРАН

строки также могут быть нулевые символы. Фактически BSTR - это указатель на строку. Его тип в Фортране - INTEGER(4).

С BSTR-строками связаны приведенные в табл. 12.4 процедуры. Все они, кроме подпрограммы SysFreeString, являются функциями типа INTEGER(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 отсутствуют интерфейсы функций SysAllocStringByteLen, 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