Объект OLE

From SunFlurry wiki
Jump to: navigation, search
  OLE (Объект OLE)
Статус разработки: Реализован
Создание объекта: Create

Объект OLE (Object Linking and Embedding) позволяет получить доступ к функциям операционной системы и других программ из программных модулей клиента, если эти программы поддерживают интерфейс COM (Component Object Model). Microsoft создали достаточно много терминов для OLE-объектов: OLE, COM, OCX, ActiveX, все они в каком-то роде означают один и тот же способ работы с внешними объектами. Самый большой минус такого способа работы заключается в том, что OLE-сервер не может контролировать время исполнения методов объектов. Это может привести к тому, что если в методе OLE-объекта есть ошибка, и метод зависнет или выдаст на экран модальное сообщение, OLE вызов никогда не вернет управление программе. Для визуального клиента это имеет меньшее значение, так как пользователь сможет перезапустить программу, однако, для консольных клиентов это весьма опасно, поэтому для консольных клиентов рекомендуется использовать функции сторожевого пса.

Система работает с интерфейсом COM в режиме STA (Single-Threaded Apartment) для визуальных (GUI) объектов и в режиме MTA (Multithreaded Apartments) для объектов, не связанных с визуальными формами. Объект связан с визуальными формами, если он располагается на визуальной форме или в таблице SFT, а также если он был создан с прямым указанием на его визуальность. Режим STA для объектов означает, что объект, созданный в одном потоке (основном визуальном потоке), не может быть доступен в других потоках. Windows позволяет вызов методов из других потоков, но это происходит с помощью стандартной очереди сообщений Windows, что идеально подходит для визуальный объектов, созданных в основном потоке системы, однако, такие вызовы исполняются несколько медленнее. Также существует особый однопоточный режим работы OLE-объектов, работающий в режиме STA, если по какой-то причине использование многопоточного режима недопустимо для конкретного OLE-объекта (к примеру, если объект должен работать как строго однопоточный). Ниже дана сводная таблица всех режимов OLE-объектов системы:

  • Режим STA (однопоточный режим). OLE-объекты, созданные таким образом, делятся на две категории:
    • Визуальные OLE-объекты, находящиеся на формах или в электронных таблицах. Такие объекты позволяют вызовы из разных потоков, так как визуальный поток обрабатывает сообщения из очереди сообщений. Вызовы из других потоков для этой категории объектов будут обладать такими же минусами, как и вызовы к объектам, созданным в режиме "центрального потока" (см. ниже).
    • Режим исполнения центрального потока. OLE-объекты создаются с помощью функции CreateThreadedOLE в специально выделенном для этого потоке, который в дальнейшем обслуживает все обращения из других потоков. Обращения происходят не с помощью использования стандартной очереди сообщений Windows, а с помощью более быстрой межпоточной синхронизации. Однако, так как все OLE-объекты, созданные в системе таким образом, обслуживает только один поток, может получиться ситуация (особенно с консольными серверами), когда выполнение вызова к объекту будет задержано, пока выполняется вызов из другого потока. В визуальных клиентах, где количество одновременно работающих потоков мало, это не будет являться реальным ограничением.
  • Режим MTA (многопоточный режим). OLE-объекты, созданные программно. Методы таких объектов могут быть вызваны из любых потоков, а не только из потока, где эти объекты были созданы. Не все OLE-объекты полностью поддерживают многопоточность, поэтому, если объект будет использоваться сразу в нескольких потоках (возможно более одного вызова в одно и то же время из разных потоков), необходимо предусмотреть какую-либо систему межпоточной синхронизации (к примеру с помощью функции LockObject). Чаще всего, однако, такие объекты создаются, чтобы выполнить определенную работу, и после этого удаляются, поэтому, многопоточность не вызывает проблем в работе. Некоторые объекты, не поддерживающие многопоточность, даже если их создавать в режиме MTA, будут работать только потоке, который создал объект (вызовы из других потоков будут вызывать исключения). В этом случае, использование CreateThreadedOLE уже является необходимостью, если с объектом предполагается работать из нескольких потоков.

В системе OLE-объекты могут присутствовать:

  • Объекты, созданные программно CreateOLE
  • Объекты, расположенные на формах. В этом режиме, объект добавляется на форму в момент ее создания в Студии, для таких объектов могут быть заданы визуальные события COM.
  • Объекты, внедренные в электронные таблицы. Такие объекты также можно добавлять программно или при копировании частей таблицы с помощью функций типа CopyByX.

Некоторые аргументы OLE функций могут представлять собой массивы. В этом случае, программа должна передать список одинаковых по типу элементов (OLE не поддерживает списки с разными типами данных). Если OLE функция возвращает массив, он автоматически будет превращен в список.

Система обычно работает с простыми типами, максимально совместимыми по размеру с OLE-оригиналами. Однако, не для всех OLE-объектов есть возможность узнать и передать требуемый объектом тип аргумента. Это происходит, если объект не указывает необходимый ему тип в свойствах библиотеки. К примеру, OLE функция во втором аргументе ожидает массив из чисел без знака длиной 2 байта (одно слово), однако, тип этого аргумента указан как VT_VARIANT (т.е. произвольный тип). Если программа передаст функции список значений с числами, система не будет знать, какой тип чисел задавать в массиве и может создать массив из 32-битных целых чисел, который не будет принят вызываемой функцией. Чтобы обойти эту проблему, необходимо использовать вспомогательную функцию OLEVariant, позволяющую из объекта системы создать особый OLE ориентированный объект с твердо заданным типом данных. При этом тип данных указывается, как константа OLE (см. константы типов данных OLE).

Как альтернативный вариант, при передаче числовых массивов в аргументе функции, тип данных в массиве может быть указан, как наименование первого элемента массива. При этом принимаются следующие типы данных:

  • I1 -- числа -128..+127 (байт со знаком)
  • UI1 -- числа 0..255 (байт без знака)
  • I2 -- числа -32768..+32767 (слово со знаком)
  • UI2 -- числа 0..65535 (слово без знака)
  • I4 -- числа -2147483648..+2147483647 (32-битное число со знаком)
  • UI4 -- числа 0..4294967295 (32-битное число без знака)
  • I8 -- 64-битные числа со знаком
  • UI8 -- 64-битные числа без знака
  • N -- числа со знаком 32 или 64 бита в зависимости от разрядности исполняемого процесса
  • UN -- числа без знака 32 или 64 бита в зависимости от разрядности исполняемого процесса

Ниже дан пример использования OLEVariant для задания типа массива данных (функция OLEVariant может использоваться не только для задания типов массивов, но и для обычных объектов):

//OLE функция Foo требует во втором аргументе массив 32-битных чисел без знака
//Создаем массив
aList:=List.Create(1,2,3,4,5,6,7,8,9,10);

aOle.Foo("Параметр 1",OLEVariant(aList,_OLE_VT_ARRAY+_OLE_VT_UI4));

Тот же самый пример, однако, в массиве используется прямое указание на тип данных:

//OLE функция Foo требует во втором аргументе массив 32-битных чисел без знака
//Создаем массив
aList:=List.Create(1,2,3,4,5,6,7,8,9,10);
//Устанавливаем признак: 32-битные числа без знака
aList.SetName(1,"UI4");

aOle.Foo("Параметр 1",aList);


Атрибуты и функции

Идентификатор Статус Тип Визуальная Параметры Описание
CreateOLE Реализована Функция CreateOLE(<Идентификатор объекта OLE (STRING)>):<Новый объект OLE (OLE)> Функция создает новый объект OLE (COM) по строке идентификатора
CreateThreadedOLE Реализована Функция CreateThreadedOLE(<Идентификатор объекта OLE (STRING)>):<Новый объект OLE (OLE)> Функция создает новый объект OLE (COM) по строке идентификатора. Объект работает в режима STA, однако, может быть доступен в любом потоке, не только в том, который создал объект. Вызовы к таким объектам осуществляются несколько медленнее.
OLEVariant Реализована Функция OLEVariant(<Объект>,<Тип данных OLE (INT)>):<Объект, используемый при вызовах OLE функций (OLEVARIANT)> Функция создает из объекта системы вспомогательный объект OLEVARIANT с заданным типом данных OLE. Функция может быть вызвана для любого объекта, однако, только следующие объекты имеет смысл превращать в объекты OLE: числа, строки, даты, другие OLE-объекты, списки.
OLEType Реализована Функция OLEType(<Объект OLE или OLEVariant (OLE, OLEVARIANT)>):<Числовой тип объекта (INT)> Функция получает числовой тип объекта OLE или вспомогательного типа OLEVARIANT.
OLEVariantToObject Реализована Функция OLEVariantToObject(<Объект OLEVariant (OLEVARIANT)>):<Объект системы> Функция конвертирует вспомогательный объект типа OLEVARIANT в стандартный объект системы, при этом поддеживаются массивы. Не все объекты полностью поддерживаются при конвертации, к примеру, _OLE_VT_NULL, _OLE_VT_EMPTY и _OLE_VT_UNKNOWN превращаются в пустой объект и т.п.
SetTimeout Планируется Функция OLE.SetTimeout(<Время ожидания исполнения команд в мс. (INT)>):<Предыдущее время ожидания исполнения команд в мс. (INT)> Функция задает или получает для объекта максимальное время ожидания исполнения команд. По умолчанию при создании объекта, это время равно 0 (не ограничено). При истечении времени ожидания система произведет отсоединение от текущего OLE-объекта и выполнявшаяся функция вызовет исключение.
SetEventHandler Планируется Функция OLE.SetEventHandler(<Имя события OLE объекта (STRING)>,<Имя функции-обработчика события (STRING)>,<Тип вызова события (INT)>=0) Функция сопоставляет локальную или глобальную функцию с событием OLE-объекта. Исполнение функции может происходить в трех режимах, в зависимости от аргумента тип вызова события: 0 (по умолчанию) -- функция будет вызвана, как прерывающее событие в контексте текущей формы (работает только для визуальных форм), 1 -- для вызова функции будет создан отдельный поток (как это происходит при вызове функции ExecuteFunctionInSeparateThread) (работает для любого контекста, но создание нового потока для часто исполняемых событий может замедлить работу системы), 2 -- событие будет помещено в очередь ожидания и будет исполнено в момент вызова функции OLESleep (работает для любого контекста).
OLESleep Планируется Функция OLE.OLESleep(<Время ожидания появления события (INT)>) Функция ожидает появления OLE события (только для событий, сопоставленных в режиме 2, см. SetEventHandler). Событие исполняется, если оно ожидает в очереди на начало вызова функции или происходит в течение времени ожидания функции. Событие будет вызвано в текущем потоке и будет иметь доступ ко всем его переменным. При задании аргумента равным нулю, событие будет исполнено, только если оно ожидает в очереди на момент вызова функции, ожидания события не будет.
dbgOLEMethodsList Реализована Функция dbgOLEMethodsList(<OLE-объект (OLE)>):<Дерево методов и свойств объекта (TREE)> Отладочная функция, позволяет получить внутренний список имен методов и свойств OLE-объекта в виде дерева. Может использоваться, чтобы найти имя метода, если документация недоступна или недостаточно подробна.