Создание DLL на основании примера из SDK

Интеграция возможностей SpRecord в ваши приложения
Ответить
Гость

Создание DLL на основании примера из SDK

Сообщение Гость »

Здравствуйте! Я пишу внешнюю компоненту 1С для работы с SpRecord. Пишу на делфи 10.1.
Мне надо что бы моя dll могла получать сообщения от COM сервера SpRecord с событиями. Для этого я попытался интегрировать в свою dll кусок из примера CommonClient - MyCOMEventsHookUnit.
Однако, даже просто указание данного файла в uses моей компоненты приводит к крашу с Runtime еrror 217 при загрузке в 1С и даже без 1С просто при попытке регистрации dll в Windows (например через команду Regsvr32).
Без MyCOMEventsHookUnit, все остальные функции работают, получают из SpRecord данные и все такое успешно. Так же и в Windows спокойно регистрируется.
Я в делфях любитель (профи я в 1С). Можете подсказать почему происходит краш? Быть может нельзя из dll так создавать COM сервера в данном случае и нужен какой то принципиально другой подход?
MaiklKar
Сообщения: 8
Зарегистрирован: 02 апр 2018, 18:36

Re: Создание DLL на основании примера из SDK

Сообщение MaiklKar »

Что то не залогинелось сразу. Автор темы я.
Аватара пользователя
sannx
Администратор
Сообщения: 2306
Зарегистрирован: 02 ноя 2011, 14:00
Skype: sann-x
Контактная информация:

Re: Создание DLL на основании примера из SDK

Сообщение sannx »

Поищите здесь на форуме темы про интеграцию с 1С. Можете обратиться к пользователям, у которых что-то получалось, написав им на е-маил или в личку.
MaiklKar
Сообщения: 8
Зарегистрирован: 02 апр 2018, 18:36

Re: Создание DLL на основании примера из SDK

Сообщение MaiklKar »

Вопрос не про интеграцию с 1С. Я просто озвучил решаемую задачу.
Забудем про 1С.... скажем я просто пишу некую DLL для каких-то своих задач. Обычную делфевую DLL. В примере SDK - CommonClient - используется юнит MyCOMEventsHookUnit.
В своей DLL я реализовал подключение к библиотеке SDK (так же как в примере CommonClient). Моя DLL успешно подключается, получает номера версий, списки каналов. Проблема возникает, когда я хочу реализовать в своей DLL получение событий так же как оно реализовано в MyCOMEventsHookUnit (без каких либо изменений кода... ну разве что GUID поменял). Компиляция моей dll происходит успешно, без ошибок и предупреждений. Но, даже не доходя до 1С, просто команда в системе Regsvr32 приводит к крашу (полагаю что и в 1С краш происходит по той же причине, но фиг с ним... не рассматриваем 1С). Методом исключения я определил что краш возникает просто при объявлении MyCOMEventsHookUnit в uses, даже без использования её в коде.
Вопрос - почему возникает краш. Может в dll нельзя использовать классы типа TAutoObject... может что то еще. Может я, по неопытности, вообще задаю неправильный вопрос. Я пока не смог нагуглить что именно не так. Быть может вы подскажете хотя бы направление куда копать.
Прикладываю часть кода относящуюся к этому вопросу и скрины ошибок.
Вложения
Код и скрины ошибок.7z
код и скрины ошибок
(66.16 КБ) 401 скачивание
Аватара пользователя
sannx
Администратор
Сообщения: 2306
Зарегистрирован: 02 ноя 2011, 14:00
Skype: sann-x
Контактная информация:

Re: Создание DLL на основании примера из SDK

Сообщение sannx »

К сожалению, по событиям я не смогу помочь. Вы можете поискать в интернете общую информацию про события от COM-объектов в dll. Это общая проблема, а не частная, привязанная к нашему SDK. Другой вариант - не использовать события, а через короткие промежутки времени опрашивать на наличие сообщений от SDK.
MaiklKar
Сообщения: 8
Зарегистрирован: 02 апр 2018, 18:36

Re: Создание DLL на основании примера из SDK

Сообщение MaiklKar »

Вас понял. Буду искать сам.
MaiklKar
Сообщения: 8
Зарегистрирован: 02 апр 2018, 18:36

Re: Создание DLL на основании примера из SDK

Сообщение MaiklKar »

Продолжение истории...
Отказался от событий COM.
Воспользовался стандартным функционалом делфи - потоками TThread .
Т.е. Есть основной класс, где создается и храниться вся информация. Там же происходит подключение к COM серверу SpRecord и все такое.
После создания COM объекта SpRecrod (успешного) и подключения к нему (то же успешного), инициирую поток, который каждые 1000 миллисекунд должен выполнять метод PeekMessage из функционала Sprecord (ссылка на переменную основного класса передается при создании потока). В итоге поток висит именно на выполнении метода PeekMessage. Просто висит без всяких крашей и сообщений.
Методом исключения все проверил.
- Поток без вызова PeekMessage работает без проблем.
- Так же без проблем поток выполняет любые методы основного класса не связанные с обращением к методам COM объекта SpRecord.
- Вызов других методов SpRecord, кроме PeekMessage , так же приводит к зависанию потока. Пробовал например GetLibVersion.
- Вызовы методов SpRecord из методов моего основного класса (не в потоке) работают корректно, не приводя к зависанию.
- Проверял это как в своей dll так и прямо на примере CommonClient - результаты абсолютно идентичны.

Скажите это опять общий вопрос про делфи или все же вопрос к функционированию SDK SpRecord ?
Аватара пользователя
sannx
Администратор
Сообщения: 2306
Зарегистрирован: 02 ноя 2011, 14:00
Skype: sann-x
Контактная информация:

Re: Создание DLL на основании примера из SDK

Сообщение sannx »

Coinitialize вызывали в начале потока?
MaiklKar
Сообщения: 8
Зарегистрирован: 02 апр 2018, 18:36

Re: Создание DLL на основании примера из SDK

Сообщение MaiklKar »

Нет. Нигде таким не пользовался. Ушел гуглить. Если дадите пример, буду благодарен.
Аватара пользователя
sannx
Администратор
Сообщения: 2306
Зарегистрирован: 02 ноя 2011, 14:00
Skype: sann-x
Контактная информация:

Re: Создание DLL на основании примера из SDK

Сообщение sannx »

Это общий вопрос для работы с СОМ-объектами в потоках. Гуглите в яндексе. Например, вот.
MaiklKar
Сообщения: 8
Зарегистрирован: 02 апр 2018, 18:36

Re: Создание DLL на основании примера из SDK

Сообщение MaiklKar »

Итого. Пишу для тех, кто наступит на те же грабли что и я.
Coinitialize не помог.
Менял модели апартаментов и STA и MTA - не помогло.
Пробовал делать маршалинг (в модели STA) - получил AV при попытке обратиться к методу COM объекта.

Для реализации второго потока на базе примера CommonClient, помогло сочетание явного указания апартаментов MTA и использования метода Synchronize во вспомогательном потоке (маршалинг не потребовался, что для MTA логично).
Для DLL компоненты добился нужного мне функционала просто путем создания другого COM объекта внутри вспомогательного потока. Так как все эти COM объекты получают одни и те же события от одной и той же АТС - получилась просто параллельная обработка одних и тех же данных. Мне нужна была только независимая от основного потока реакция на события - я её получил.
Я не настолько уверен в своих знаниях Delphi что бы утверждать что все мои пробы были корректны с точки зрения языка и приведения ссылок. Есть только предположение что зависания при обращении к методам COM во вспомогательном потоке как то связанны с тем, что в DLL нет объекта типа формы с обработкой очереди сообщений. Но тогда непонятно почему тогда в одном потоке все прекрасно работает.
Спасибо sannx за терпение в ответах на мои вопросы :)
Ответить