Отличие CALL и обычного вызова процедуры ?!?

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Митрий
Новичок
Сообщения: 15
Зарегистрирован: 02 Февраль 2006, 14:33
Откуда: Тамбов

Отличие CALL и обычного вызова процедуры ?!?

Сообщение Митрий »

Уважаемые знатоки! Прошу по-возможности оперативного ответа.
:( НЕ МОГУ РАЗОБРАТЬСЯ С ОШИБКОЙ! В чём отличие CALL и обычного вызова процедуры ?!?

Имеется собственная DLL и в ней среди других процедура XPROC, которая открывает окно, выбирает данные из БД в Queue, затем выгружает данные в Excel. Эта процедура для работы использует другие DLL.
Имеется два похожих приложения с вызовом ЭТОЙ процедуры из ЭТОЙ DLL :shock: . Разница в том, что в ПЕРВОМ приложении ЭТА библиотека подключена сразу в проекте и вызов процедуры осуществлён через 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.
Как избавиться от ошибки во ВТОРОМ приложении :?:
Аватара пользователя
StillZero
Ветеран
Сообщения: 454
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Контактная информация:

Сообщение 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):

Код: Выделить всё

hTheme = PXP:OpenThemeData(0, szThemeName)
пример выдран из XP-Theme от PowerOffice

удачи
Митрий
Новичок
Сообщения: 15
Зарегистрирован: 02 Февраль 2006, 14:33
Откуда: Тамбов

Сообщение Митрий »

Простите, уважаемый StillZero!
Но Вы невнимательны :twisted: . Я не спрашивал про аналог оператора CALL
(правда, извините, я не сказал, что это пробовано - результат тот же).
Запуск проходит во всех случаях нормально.
ВОПРОС в другом: прога ВАЛИТСЯ :( во время выгрузки в Excel - ТОЛЬКО :!: если процедура запущена посредством CALL (или приведённого Вами аналогичного метода) !
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Re: Отличие CALL и обычного вызова процедуры ?!?

Сообщение Yufil »

Митрий писал(а):Уважаемые знатоки! Прошу по-возможности оперативного ответа.
:( НЕ МОГУ РАЗОБРАТЬСЯ С ОШИБКОЙ! В чём отличие CALL и обычного вызова процедуры ?!?

Имеется собственная DLL и в ней среди других процедура XPROC, которая открывает окно, выбирает данные из БД в Queue, затем выгружает данные в Excel. Эта процедура для работы использует другие DLL.
Имеется два похожих приложения с вызовом ЭТОЙ процедуры из ЭТОЙ DLL :shock: . Разница в том, что в ПЕРВОМ приложении ЭТА библиотека подключена сразу в проекте и вызов процедуры осуществлён через 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) - запустится процедура с указанным адресом.
Митрий
Новичок
Сообщения: 15
Зарегистрирован: 02 Февраль 2006, 14:33
Откуда: Тамбов

Сообщение Митрий »

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

ПРОШУ ЕЩЁ ОТКЛИКОВ. :roll:
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Сообщение Yufil »

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

ПРОШУ ЕЩЁ ОТКЛИКОВ. :roll:
А какой смысл вызывать по Call, если не секрет? Почему нельзя процедуру откомпилировать просто как автономную DLL?

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

Сообщение Митрий »

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

А не правы Вы :roll: , как я начал понимать в следующем:
При передаче команд "ВЕЛИКОЛЕПНОМУ" используется последовательно UNLOCKTHREAD(), <команда>, LOCKTHREAD().

А между тем главный процесс получает события, такие, например, как EVENT:TIMER.

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

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

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

Сообщение Yufil »

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

А не правы Вы :roll: , как я начал понимать в следующем:
При передаче команд "ВЕЛИКОЛЕПНОМУ" используется последовательно UNLOCKTHREAD(), <команда>, LOCKTHREAD().

А между тем главный процесс получает события, такие, например, как EVENT:TIMER.

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

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

НО ПРОБЛЕМА ОСТАЛАСЬ! ПОМОГИТЕ СОВЕТОМ:
Если пользователь щёлкает мышью в других окнах - события ведь происходят, управление внезапно передаётся другому ACCEPT'у и повторяется прежний дрянной эффект.
Как же :shock: запретить это щёлканье...?
Понятно... и с этим потыкался... С этого и надо было начинать. Лучший вариант - перейти на CW6
А здесь надо деактивировать OLE на Event:LoseFocus и снова активировать на Event:GainFocus. А ещё перед закрытием окна уничтожить OLE командой Destroy.
Митрий
Новичок
Сообщения: 15
Зарегистрирован: 02 Февраль 2006, 14:33
Откуда: Тамбов

Сообщение Митрий »

Уважаемый Бааааааальшой Гуру 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. Как же это поймать.
НЕ ДОГОНЯЮ :shock: ...
Митрий
Новичок
Сообщения: 15
Зарегистрирован: 02 Февраль 2006, 14:33
Откуда: Тамбов

Сообщение Митрий »

Ну что, умнейшие!
Отзовитесь! Может кто-нибудь что-нибудь посоветовать?
Например, как заблокировать клаву и мышь, а потом отпустить?
Или другой путь :cry:
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Сообщение 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, давай в Аське потрындим....
Аватара пользователя
Admin
Администратор
Сообщения: 3959
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 25 раз
Поблагодарили: 22 раза
Контактная информация:

Сообщение Admin »

Yufil писал(а):Уважаемый Бааааааальшой Гуру Yufil!
Это не я себя так назвал, а администратор сайта. И нечего иронизировать...
Не стебитесь над званием!
Человек всегда может ошибаться а звание дают за заслуги перед обществом :)
А то я могу и того кто любит шутить .... Гуру каким нибудь сделать :)
Рай совершает ошибки ничуть не реже чем ад. Просто у него хорошая пресса
Митрий
Новичок
Сообщения: 15
Зарегистрирован: 02 Февраль 2006, 14:33
Откуда: Тамбов

Сообщение Митрий »

Прости, Admin!
Я не нарочно. Это была беззлобная шутка :wink: .
Не хотел сделать больно :( .
Учту :D .
Ответить