Глава 5
Информация о версии
В данной главе представлены различные сведения характерные для текущей версии LuaCOM. Здесь записаны текущие ограничения LuaCOM, известные его ошибки, история изменений прежних версий, технические подробности и т.д.
5.1 Ограничения
Здесь перечислены текущие ограничения LuaCOM, по состоянию на данную версию, и сведения о будущем ослаблении этих ограничений.
- LuaCOM в настоящий момент поддерживает выставление COM-объектов только в качестве “одноразовых” объектов. Ограничение можно обойти выставлением одного и того же объекта много раз. Это ограничение может быть удалено по запросу;
- LuaCOM не поддерживает методы COM с переменным числом параметров. Ограничение можно обойти передачей дополнительных (необязательных) параметров внутри таблицы, но это не проверялось. Это может быть выполнено по запросу;
- LuaCOM не предоставляет доступ к интерфейсам COM которые не наследуют от интерфейса IDispatch. То есть, поддерживается только автоматизация объектов.
Это ограничение обусловлено функцией позднего связывания, предоставляемой LuaCOM.
Имеется возможность предоставления доступа к этим COM-интерфейсам через ”посредничество” объекта Automation, который переводит вызовы, сделанные через автоматизацию к вызовам (раннее связывание).
Также возможно реализовать такого ”посредника” напрямую с помощью API C/C++ LuaCOM, но это не проверялось и не испытывалось.
5.2 Известные ошибки
Здесь перечислены известные ошибки в LuaCOM. Если найдете любые другие ошибки, сообщите о них через домашнюю страницу LuaCOM.
- LuaCOM реализует только интерфейсы позднего связывания, но допускает QueryInterface для интерфейсов раннего связывания. Такое ошибочное поведение обусловлено способом отправки событий клиента Visual Basic к серверу. Смотрите подраздел 5.4.5;
- когда таблица объектов (то есть, SAFEARRAY из указателей IDispatch) передается в качестве параметра COM-объекту, эти объекты LuaCOM не могут быть удалены автоматически и может произойти утечка;
- когда COM-объект, реализованный в Lua, вызывается из VBScript, параметры “in-out” типа SAFEARRAY не могут быть изменены. Если таковые есть, VBScript пожалуется на ошибку COM.
5.3 Дальнейшие улучшения
Помимо усовершенствований перечисленных в главах ?? и ??, есть и другие запланированные улучшения:
- улучшение общей производительности LuaCOM;
- динамическое создание библиотек типов;
- улучшение поддержки создания полноценных объектов COM с помощью Lua.
5.4 Значимые проблемы LuaCOM
LuaCOM в использовании очень похож на другие языки с поддержкой Automation или среды разработки (Visual Basic
®, VBA, VBScript™, pycom и т.д.).
Тем не менее, есть некоторые тонкие различия, которые могут запутать программиста: другой синтаксис, неожиданное поведение и т.д.
Чтобы облегчить задачу пользователю LuaCOM, здесь мы объединили сведения об этих проблемах.
5.4.1 Проблемы создания экземпляра (инстанцирования) объектов COM
Некоторые COM-объекты могут располагаться во внутрипроцессных серверах (реализованных в DLL'ках) и в локальных серверах (реализованных как отдельные процессы).
COM отдает предпочтение внутрипроцессным серверам, так как они более быстрые.
Тем не менее, некоторые приложения могут не работать с LuaCOM, работающим в качестве внутрипроцессных серверов.
Следует создавать экземпляр COM-объекта предоставляя дополнительный флаг, заставляющий использовать локальные серверы. Смотрите документацию по функции API
CreateObject.
5.4.2 Реализация COM-объектов из памяти
В обычной ситуации внепроцессный COM-сервер должен завершить существование когда высвободятся все ссылки на его объекты.
Это может иметь важное значение, так как создание новых экземпляров может зависеть от отсутствия работающего сервера.
LuaCOM объединяет стандартный механизм подсчета ссылок COM со сборщиком мусора Lua.
Это прекрасно работает в большинстве ситуаций, но имеются несколько случаев, в которых требуется более тщательный анализ:
- для немедленного завершения серверного процесса, необходимо удалить все ссылки в Lua на COM-объекты, находящиеся в этом процессе, и затем вызвать цикл сборки мусора;
- иногда ссылка на COM-объект может быть ошибочно сохранена в глобальной переменной и впоследствии там забыта. Это может помешать завершению серверного процесса, даже при вызове такого метода, как “Quit”.
Чтобы уйти от этой проблемы, можно сгруппировать все ссылки на COM-объект и его вложенные объекты в одной таблице, во избежание “потерянных” ссылок.
Для более подробной информации, смотрите
главу 4.
5.4.3 Получение событий
Для получения событий и уведомлений от COM-объекта необходимо установить соединение с помощью точек подключения.
Но этого не достаточно: для получения этих уведомлений клиентское приложение должно иметь работающий цикл обработки сообщений. Для более подробной информации, смотрите
главу 3.3.3.
5.4.4 Расширяемые интерфейсы
Некоторые объекты, имеющие типовые сведения описывающие их интерфейсы (методы, свойства, типы параметров и т.д.), могут дополняться новыми методами и свойствами во время выполнения.
Это означает, что эти методы и свойства могут быть доступны только с тем же самым механизмом LuaCOM, используемым для универсального COM-объекта. Из этого есть несколько выводов:
- при обращении к свойствам, обязательно обращаться к ним как к методам и использовать префикс set для изменения их значений.
Если объект foo имеет свойство color, не представленное в типовых сведениях, к нему можно обратиться только через foo:color() (доступ чтения) или foo:setcolor() (доступ записи);
- при вызове методов, все параметры рассматриваются как “in-out”. Это означает, что помимо возвращаемого значения, вызов к методу этого типа будет возвращать назад все параметры, независимо от того, были ли они изменены вызываемым.
В любом случае, можно игнорировать эти значения, просто не назначая их в переменную, например: x = foo:method(a,b) будет игнорировать значения a и b, также возвращенные вызовом.
Такое поведение имеют COM-объекты связанные с WMI. Для более подробной информации, смотрите главу ??.
5.4.5 Проблема Visual Basic®
COM-сервер реализованный с помощью LuaCOM можно без проблем использовать в Visual Basic.
Public lc as Object
Set lc = CreateObject("MyCOMObject.InLuaCOM")
lc.showWindow
b = lc.getData(3)
lc.Quit
Но если нужно принимать события, сгенерированные COM-объектом, реализованным с помощью LuaCOM, то необходимо использовать
Public WithEvents от Visual Basic:
Public WithEvents obj as MyCOMObject.Application
Set obj = CreateObject("MyCOMObject.Application")
Private Sub obj_genericEvent()
’ Put your event code here (поместите здесь код события)
End Sub
Здесь имеется проблема: когда VB (т.е. Visual Basic) присваивает результат
CreateObject переменной
obj, он пытается получить интерфейс раннего связывания (насколько я знаю, VB использует интерфейсы позднего связывания только с переменными типа
Object).
LuaCOM не работает с интерфейсами раннего связывания (известного как vtable).
Если вызвать любой метод, использующий переменную
obj, VB выдаст исключение.
Принятое решение состояло в том, чтобы допустить QueryInterface для интерфейса раннего связывания таким образом, разрешается использование
Public WithEvents). Теперь клиент должен делать “преобразование типа” для правильного использования COM-объекта:
Public WithEvents obj_dummy as MyCOMObject.Application
Public obj as Object
Set obj_dummy = CreateObject("MyCOMObject.Application")
Set obj = obj_dummy
Таким образом клиент может вызывать методы COM-объекта с помощью переменной
obj.
5.5 История версий
Версия 1.4
- Официальная поддержка Lua 5.1 (Lua 4.0/5.0 больше не поддерживается).
- Makefile обновлен до MSVC++2005. Включены файлы проекта Visual Studio MSVC++2005 и VC6 (.sln/.vcproj + .dsp).
- Исправления SafeArray: Исправлена обработка пустых SafeArrays и одномерных SafeArrays; Исправлен обратный порядок индексов в многомерных SafeArray; Добавлен новый демонстрационный пример safearrays.
- Исправлена обработка с вложенными нолями. Bug428.
- Поддержка HtmlHelp в luacom.ShowHelp. Feature2010.
- Переименован файл luacom-lua5-1.3.dll в luacom.dll.
- Другие исправления ошибок, таких как улучшение кода и параметров (Смотрите Tracker на странице проекта LuaForge.)
Версия 1.3
- Поддержка нового предложения Lua пакета (смотрите http://www.keplerproject.org/compat)
- Контролы OLE со встроенным UI (интерфейсом);
- Представление variants в таблицах;
- Конвертирование tag/metamethod для таблиц;
- Представление дат в таблицах;
- К объекту можно подключать более одного приемника событий;
- Метод typelibs, возвращенный GetTypeInfo, экспортирует все перечисления библиотеки типов в таблицу;
- Удаление из регистра зарегистрированных серверов (отмена регистрации);
- Определяет, когда указатель интерфейса на самом деле является локальной Lua таблицей, реализующей COM-объект;
- Исправлена утечка памяти с некоторыми из параметров;
- Удален разрыв строки в некоторых системных исключениях.
Версия 1.2
- Может быть загружена функция require от Lua 5 версии;
- Внутрипроцессные серверы полностью реализованы на Lua (код инициализации на C стал не нужен для внутрипроцессных серверов и для локальных серверов использующих Lua 5);
- Теперь LuaCOM правильно конвертирует массивы, начинающие с 1;
- LuaCOM правильно конвертирует строки UNICODE из/в строки ANSI;
- массивы байтов теперь преобразуются в/из строки с включением нолей;
- LuaCOM имеет теперь ограниченную поддержку загрузки и просмотра типовых сведений и библиотек типов.
При этом включена возможность импорта констант библиотеки типов (enum) как глобальных переменных Lua и возможность открытия справочной информации, связанной с компонентом;
- теперь поддерживаются объекты, реализующие интерфейс IEnumVARIANT. Это означает, что в LuaCOM могут использоваться коллекции, тем же способом как в VBScript™;
- для упрощения отладки реализован механизм ведения журнала;
- Теперь LuaCOM корректно обрабатывает вызовы COM с . Это вызывало проблемы при получении событий Microsoft Excel®;
- теперь появилась возможность указать контекст, используемый для создания экземпляра COM-объекта (будет ли он создан как локальный сервер, или как внутрипроцессный сервер);
- удален не-ANSI код;
- при встрече с указателем IUnknown, LuaCOM теперь запрашивает его на принадлежность к IDispatch или IEnumVARIANT интерфейсам, возвращая объект LuaCOM вместо указателя IUnknown;
- улучшена обработка ошибок: теперь LuaCOM позволяет настраивать действия, который нужно принять при возникновении ошибок;
- LuaCOM теперь поддерживает понятие метода по умолчанию: когда кто-то использует ссылку на объект LuaCOM как функцию, LuaCOM делает вызов функции при помощи метода по умолчанию для этого объекта;
- теперь часть LuaAPI в LuaCOM реализована на Lua 5. Это облегчает добавление новых функций и позволяет избежать переполнения библиотеки.
Тем не менее, это не повлияет на тех, кто использует бинарный выпуск, так как они несут предварительно скомпилированный Lua код;
- luacom.GetObject теперь поддерживает использование моникеров (monikers). Среди всего прочего, это делает возможным использование WMI и открывать файлы документов напрямую, например: luacom.GetObject("myfile.xls");
- luacom.CreateObject и luacom.GetObject теперь делают попытку инициализации COM-объекта через IPersistStreamInit. Некоторые объекты отказываются работать без этого шага.
Версия 1.1
- LuaCOM теперь совместим с Lua 4 и Lua 5. Это просто вопрос выбора соединения с правильной библиотекой;
- при использовании Lua 5, LuaCOM использует логические значения для лучшего соответствия типам Automation;
- все функции API Lua в LuaCOM теперь сгруппированы вместе в одной таблице по имени luacom, хотя в библиотеке версии Lua 4, они все ещё доступны глобально как luacom_<function>;
- теперь стало возможным создавать экземпляры приложений Microsoft® Office® (Excel®, PowerPoint®, и т.д.). Раньше было возможно только их использование через GetObject; теперь можно создавать новый экземпляр этих приложений с помощью luacom.CreateObject;
- при компиляции с флагом NDEBUG, LuaCOM больше не использует вывода на терминал в любом виде (printf, cout и т.д.). Это может нарушить работу некоторых приложений.
Версия 1.0
- изменено обращение к свойству: теперь к параметризованным свойствам нужно обращаться как к функциям, с использованием префикса для различия считывания и записи. Если префикс опущен, предполагается получение (считывание) свойства;
- больше не поддерживается синтаксис “obj.Property(param)”. Следует использовать двоеточие – “:” – “obj:Property(param)”;
- улучшена поддержка реализации COM-объектов, включая регистрацию и создание событий;
- переписан движок преобразования типов. Теперь он более жестко придерживается типам, указанным в библиотеках типов;
- переписана привязка для лучшей поддержки параметров “out” и “in-out”, а также ещё более строгого соблюдения рекомендованных правил распределения памяти для COM;
- теперь поддерживаются COM-объекты без типовых сведений.
Версия 0.9.2
- удалены константы LUACOM TRUE и LUACOM FALSE; теперь логические переменные следуют таким же соглашениям как в языке C;
- исправлены утечки в памяти и интерфейсе;
- некоторые функции API имеют немного различающиеся имена;
- изменения в политике распределения памяти, чтобы более строго следовать практике, рекомендованной в COM документации;
- изменена политика передачи параметров;
- добавлена ограниченная поддержка указателей IUnknown;
- изменения в преобразовании типа;
- добавлена ограниченная поддержка для внедрения и регистрации объектов COM в Lua
Версия 0.9.1
- переход на Lua 4;
- улучшение обработки различных видов типовых сведений (например, теперь можно получить доступ к объекту Microsoft Internet Explorer®);
- исключения и ошибки теперь обрабатываются более корректно;
- добавлена поддержка для дополнительных (необязательных) параметров со значениями по умолчанию;
- LuaCOM больше не делает инициализацию библиотек COM; это остается на усмотрение пользователя;
- более строгое поведение у синтаксиса вызовов метода и доступа к свойствам (методы с “:”, свойства с “.”).
LuaCOM был разработан Renato Cerqueira, Vinicius Almendra и Fabio Mascarenhas.
Проект финансируется компанией TeCGraf
(Technology Group on Computer Graphics).