Страница 1 из 1
Отличие CALL и обычного вызова процедуры ?!?
Добавлено: 03 Сентябрь 2006, 13:27
Митрий
Уважаемые знатоки! Прошу по-возможности оперативного ответа.

НЕ МОГУ РАЗОБРАТЬСЯ С ОШИБКОЙ! В чём отличие CALL и обычного вызова процедуры ?!?
Имеется собственная DLL и в ней среди других процедура XPROC, которая открывает окно, выбирает данные из БД в Queue, затем выгружает данные в Excel. Эта процедура для работы использует другие DLL.
Имеется два похожих приложения с вызовом ЭТОЙ процедуры из ЭТОЙ DLL

. Разница в том, что в ПЕРВОМ приложении ЭТА библиотека подключена сразу в проекте и вызов процедуры осуществлён через START(XPROC, 25000), а во ВТОРОМ приложении происходит динамическая загрузка этой процедуры с помощью
START(StartXProc,25000), где:
StartXProc Procedure
Code
Call(NameOfDLL, 'XPROC@xxx', 1)
Так вот, ПЕРВОЕ приложение работает отлично. ВТОРОЕ приложение в процессе выгрузки в Excel внезапно обрывается в различных местах хода выгрузки.
Системным отладчиком установлен отладчик CLARION. При обрыве отладчик сообщает: "Unknown exception", а затем "Stack overflow" ИЛИ "память не может быть READ", а затем "Access violation".
В окне отладчика "Stack Trace" последним процессом является "Unknown", а выше одна из процедур библиотеки выгрузки в Excel (разная).
Использую C55, Legacy. Win-2k Server. MSOffice XP.
Как избавиться от ошибки во ВТОРОМ приложении

Добавлено: 03 Сентябрь 2006, 16:44
StillZero
В чём отличие CALL и обычного вызова процедуры
хз
Call(NameOfDLL, 'XPROC@xxx', 1)
Как вариант: использовать LoadLibrary и GetProcAddress для динамической загрузки DLL и вызова процедуры.
прототипы api-функций:
Код: Выделить всё
PXP:LoadLibrary(*CSTRING pszModuleFileName),UNSIGNED,PASCAL,RAW,NAME('LoadLibraryA')
PXP:FreeLibrary(UNSIGNED hModule),BYTE,PASCAL,RAW,NAME('FreeLibrary'),PROC
PXP:GetProcAddress(UNSIGNED hModule,*CSTRING pszProcName),LONG, PASCAL,RAW,NAME('GetProcAddress')
примерный код:
в inc-файле или в глобалах описываешь прототип твоей функции:
Код: Выделить всё
MODULE('External')
PXP:OpenThemeData(UNSIGNED hWnd, BSTRING CwStr),UNSIGNED,RAW,PASCAL,DLL(__OpenThemeData_)
END
собственно код загрузки:
Код: Выделить всё
__UXThemeLibrary_ LONG
szLibName CSTRING(255)
szProcName CSTRING(255)
__OpenThemeData_ LONG,STATIC,NAME('PXP:OpenThemeData')
code
szLibName = 'uxtheme.dll'
__UXThemeLibrary_ = PXP:LoadLibrary(szLibName)
szProcName = 'OpenThemeData'
__OpenThemeData_ = PXP:GetProcAddress(__UXThemeLibrary_, szProcName)
вызов процедуры в обычном коде (т.е. вместо call):
пример выдран из XP-Theme от PowerOffice
удачи
Добавлено: 04 Сентябрь 2006, 9:42
Митрий
Простите, уважаемый StillZero!
Но Вы невнимательны

. Я не спрашивал про аналог оператора CALL
(правда, извините, я не сказал, что это пробовано - результат тот же).
Запуск проходит во всех случаях нормально.
ВОПРОС в другом: прога ВАЛИТСЯ

во время выгрузки в Excel - ТОЛЬКО

если процедура запущена посредством CALL (или приведённого Вами аналогичного метода) !
Re: Отличие CALL и обычного вызова процедуры ?!?
Добавлено: 04 Сентябрь 2006, 9:52
Yufil
Митрий писал(а):Уважаемые знатоки! Прошу по-возможности оперативного ответа.

НЕ МОГУ РАЗОБРАТЬСЯ С ОШИБКОЙ! В чём отличие CALL и обычного вызова процедуры ?!?
Имеется собственная DLL и в ней среди других процедура XPROC, которая открывает окно, выбирает данные из БД в Queue, затем выгружает данные в Excel. Эта процедура для работы использует другие DLL.
Имеется два похожих приложения с вызовом ЭТОЙ процедуры из ЭТОЙ DLL

. Разница в том, что в ПЕРВОМ приложении ЭТА библиотека подключена сразу в проекте и вызов процедуры осуществлён через START(XPROC, 25000), а во ВТОРОМ приложении происходит динамическая загрузка этой процедуры с помощью
START(StartXProc,25000), где:
StartXProc Procedure
Code
Call(NameOfDLL, 'XPROC@xxx', 1)
Так вот, ПЕРВОЕ приложение работает отлично. ВТОРОЕ приложение в процессе выгрузки в Excel внезапно обрывается в различных местах хода выгрузки.
Системным отладчиком установлен отладчик CLARION. При обрыве отладчик сообщает: "Unknown exception", а затем "Stack overflow" ИЛИ "память не может быть READ", а затем "Access violation".
В окне отладчика "Stack Trace" последним процессом является "Unknown", а выше одна из процедур библиотеки выгрузки в Excel (разная).
Использую C55, Legacy. Win-2k Server. MSOffice XP.
Как избавиться от ошибки во ВТОРОМ приложении

Второе приложение запускается в том же треде, что и вызывающая процедура, а первое-в другом.
Возможно, в первом случае накладки с управлением памятью как-то
рассасываются при закрытии треда.
Можно как было указано выше извлечь адрес процедуры, а потом выполнить пуск по адресу
STARTAddr(Long,UNSIGNED=0),SIGNED,PROC,NAME('Cla$START')
... достать адрес процедуры
StartAddr(ProcedureAddress,25000) - запустится процедура с указанным адресом.
Добавлено: 04 Сентябрь 2006, 11:27
Митрий
Извините, Бальшой Гуру Yufil

!
Вы также невнимательны!
Как ни странно, но я почему-то вижу, что написано в кусочке кода,
а именно START - в ОБОИХ случаях. То есть THREAD не тот же, что и вызывающая процедура, а отдельный!
Прежние Ваши советы по CALL и API-аналогам читал и ПРОБОВАЛ.

Результат одинаков.
ПРОШУ ЕЩЁ ОТКЛИКОВ.

Добавлено: 04 Сентябрь 2006, 16:04
Yufil
Митрий писал(а):Извините, Бальшой Гуру Yufil

!
Вы также невнимательны!
Как ни странно, но я почему-то вижу, что написано в кусочке кода,
а именно START - в ОБОИХ случаях. То есть THREAD не тот же, что и вызывающая процедура, а отдельный!
Прежние Ваши советы по CALL и API-аналогам читал и ПРОБОВАЛ.

Результат одинаков.
ПРОШУ ЕЩЁ ОТКЛИКОВ.

А какой смысл вызывать по Call, если не секрет? Почему нельзя процедуру откомпилировать просто как автономную DLL?
У меня как раз есть кларионовские процедуры, вызываемые по Call+Start, это плагины к основной программе, определяющие дополнительный функционал самим фактом, приложен плагин или нет. Но для них строжайшее требование - компиляция с тем же словарём, что и основная программа. И OLE в них вызываются (правда, не Excel)
И есть некоторые танцы с бубном при подключении модуля, правда, именно для ABC, связанные с инициализацией методов GlobalErrors и IniMgr. Для модулей, вызываемых по Call они, естественно, остаются неинициализированными. Поэтому приходится их инициализировать... эээ, перректально...
Хотя, возможно, в последних версиях Кларион эта проблема и закрыта, проверить лень.
Добавлено: 04 Сентябрь 2006, 17:17
Митрий
Вы правы, уважаемый

Yufil. Потребность - плагины.
Скомпилированы с общим словарём, как и у Вас.
С инициализацией - полный порядок, это решено по образу и подобию последнего предложения Юрия Философова из старой темы "Запуск процедуры из внешней DLL" от 11.02.2004г.
А не правы Вы

, как я начал понимать в следующем:
При передаче команд "ВЕЛИКОЛЕПНОМУ" используется последовательно UNLOCKTHREAD(), <команда>, LOCKTHREAD().
А между тем главный процесс получает события, такие, например, как EVENT:TIMER.
И что особенно интересно, если процедура выгрузки в Excel работает из библиотеки, собранной CLARION'ом в приложение (1 ВАРИАНТ), то вот это самое EVENT:TIMER не поступает на ACCEPT потому как ещё не закончена обработка текущего события активного процесса.
А вот во ВТОРОМ случае

- когда вызов произведён из плагина - CLARION не почему-то понимает, что это тож его произведение и считает его "чужой процедурой" - то есть генерит событие и передаёт управление на ACCEPT другого окна, хотя обработка в текущем ACCEPTE (плагина) не закончена. И если этот момент попал между UNLOCKTHREAD и LOCKTHREAD - ВОТ ТУТ-ТО И ЕСТЬ "ГРАБЛИ"

.
То есть, используя 0{PROP:TIMER} = 0 в каждом активном окне до передачи данных в EXCEL (а затем восстанавливая прежние значения), удалось избавиться от ВЫРУБОНА

.
НО ПРОБЛЕМА ОСТАЛАСЬ! ПОМОГИТЕ СОВЕТОМ:
Если пользователь щёлкает мышью в других окнах - события ведь происходят, управление внезапно передаётся другому ACCEPT'у и повторяется прежний дрянной эффект.
Как же

запретить это щёлканье...?
Добавлено: 04 Сентябрь 2006, 17:34
Yufil
Митрий писал(а):Вы правы, уважаемый

Yufil. Потребность - плагины.
Скомпилированы с общим словарём, как и у Вас.
С инициализацией - полный порядок, это решено по образу и подобию последнего предложения Юрия Философова из старой темы "Запуск процедуры из внешней DLL" от 11.02.2004г.
А не правы Вы

, как я начал понимать в следующем:
При передаче команд "ВЕЛИКОЛЕПНОМУ" используется последовательно UNLOCKTHREAD(), <команда>, LOCKTHREAD().
А между тем главный процесс получает события, такие, например, как EVENT:TIMER.
И что особенно интересно, если процедура выгрузки в Excel работает из библиотеки, собранной CLARION'ом в приложение (1 ВАРИАНТ), то вот это самое EVENT:TIMER не поступает на ACCEPT потому как ещё не закончена обработка текущего события активного процесса.
А вот во ВТОРОМ случае

- когда вызов произведён из плагина - CLARION не почему-то понимает, что это тож его произведение и считает его "чужой процедурой" - то есть генерит событие и передаёт управление на ACCEPT другого окна, хотя обработка в текущем ACCEPTE (плагина) не закончена. И если этот момент попал между UNLOCKTHREAD и LOCKTHREAD - ВОТ ТУТ-ТО И ЕСТЬ "ГРАБЛИ"

.
То есть, используя 0{PROP:TIMER} = 0 в каждом активном окне до передачи данных в EXCEL (а затем восстанавливая прежние значения), удалось избавиться от ВЫРУБОНА

.
НО ПРОБЛЕМА ОСТАЛАСЬ! ПОМОГИТЕ СОВЕТОМ:
Если пользователь щёлкает мышью в других окнах - события ведь происходят, управление внезапно передаётся другому ACCEPT'у и повторяется прежний дрянной эффект.
Как же

запретить это щёлканье...?
Понятно... и с этим потыкался... С этого и надо было начинать. Лучший вариант - перейти на CW6
А здесь надо деактивировать OLE на Event:LoseFocus и снова активировать на Event:GainFocus. А ещё перед закрытием окна уничтожить OLE командой Destroy.
Добавлено: 04 Сентябрь 2006, 18:04
Митрий
Уважаемый Бааааааальшой Гуру Yufil!
Недопонял:
Лучший вариант - перейти на CW6
1) В CW6 такой проблемы нет?
А здесь надо деактивировать OLE на Event:LoseFocus и снова активировать на Event:GainFocus. А ещё перед закрытием окна уничтожить OLE командой Destroy.
2) Уничтожение, естствно, делаю. А что, если деактивировать OLE по утрате фокуса, а затем активировать по получении - разве я смогу отгрузить всё? Или надо начать сначала? Или с какого места - как узнать?
А ведь фокус утрачивается внезапно и непредсказуемо. И грабли-то, именно (как я понял) - когда идёт обработка события для BUTTON'а EVENT:ACCEPTED при последовательной посылке EXCEL'у РЯДА КОМАНД, т.е. вида UNLOCKTHREAD <команда1> LOCKTHREAD, UNLOCKTHREAD <команда2> LOCKTHREAD, ... UNLOCKTHREAD <команда_N> LOCKTHREAD.
И именно в момент когда исполнено UNLOCKTHREAD и не исполнено LOCKTHREAD. Как же это поймать.
НЕ ДОГОНЯЮ

...
Добавлено: 05 Сентябрь 2006, 10:59
Митрий
Ну что, умнейшие!
Отзовитесь! Может кто-нибудь что-нибудь посоветовать?
Например, как заблокировать клаву и мышь, а потом отпустить?
Или другой путь

Добавлено: 05 Сентябрь 2006, 11:11
Yufil
Уважаемый Бааааааальшой Гуру Yufil!
Это не я себя так назвал, а администратор сайта. И нечего иронизировать...
Недопонял:
1) В CW6 такой проблемы нет?
В CW6 настоящие треды, там этой проблемы действительно нет. Есть другие.
А в 55 есть только псевдотреды, которые с OLE действительно плохо сочетаются.
2) Уничтожение, естствно, делаю. А что, если деактивировать OLE по утрате фокуса, а затем активировать по получении - разве я смогу отгрузить всё? Или надо начать сначала? Или с какого места - как узнать?
Так в CW55 реально работает ровно ОДНА задача. Если идёт заполнение таблицы, переключение на другой экран невозможно.
А если произошло переключение, то таблица НЕ ЗАПОЛНЯЕТСЯ!
КОМАНД, т.е. вида UNLOCKTHREAD <команда1> LOCKTHREAD, UNLOCKTHREAD <команда2> LOCKTHREAD, ... UNLOCKTHREAD <команда_N> LOCKTHREAD.
UnlockThread/LockThread - это вообще не о том...
Это говорит, что кларионовский Accept не должен ловить сообщения.
Мой номер ICQ 75-924-439, давай в Аське потрындим....
Добавлено: 05 Сентябрь 2006, 16:54
Admin
Yufil писал(а):Уважаемый Бааааааальшой Гуру Yufil!
Это не я себя так назвал, а администратор сайта. И нечего иронизировать...
Не стебитесь над званием!
Человек всегда может ошибаться а звание дают за заслуги перед обществом

А то я могу и того кто любит шутить .... Гуру каким нибудь сделать

Добавлено: 05 Сентябрь 2006, 17:24
Митрий
Прости, Admin!
Я не нарочно. Это была беззлобная шутка

.
Не хотел сделать больно

.
Учту

.