The Russian Electronic Developer Magazine | |
Русский электронный журнал разработчика | |
В VP/2 оказался пример, реализующий библиотеку для REXX (в examples\rexx). Там описана функция VPTouch, входными параметрами для которой являются одна или несколько масок (или имен файлов), результатом являются действия (изменение timestamp файла(ов)) и код возврата (текстовая переменная).
Что полезного можно почерпнуть из этого примера? Ну во-первых заголовок функции:
Function VPTouch( FuncName : PChar; ArgC : ULong; Args : pRxString; QueueName : pChar; Var Ret : RxString ) : ULong; export;Этот заголовок должен быть одинаков для всех функций, вызываемых из рекс-программ.
FuncName - имя вызываемой функции.Как видно из примера функция возвращает только одну простую строку в качестве результата ( Var Ret : RxString ). Возвращать список процессов в одной строке неудобно, поэтому лучше использовать другой вариант. Для этого можно использовать запись в файл, очередь и еще тот замечательный способ, который использует, к примеру SysFileTree - стем. Отлично, в Watcom 10.0 как раз есть пример DLL-ки SysUtils, которая содержит эту функцию (WATCOM\SAMPLES\TOOLKT2X\REXX\REXXUTIL\). Оттуда мы и выясняем, что такая переменная создается и обрабатывается функцией RexxVariablePool (см. VP\SOURCE\RTL\OS2REXX.PAS):
ArgC - количество передаваемых аргументов.
Args - сами аргументы (в примере очень хорошо показано, как с ними обращаться, их может быть много ;)
QueueName - имя очереди (непонятно, как ее использовать, но по всей видимости результат выполнения функции может помещаться в очереди, и/или читаться из нее).
Ret - результат работы функции (при вызове var = RxMyFunc( a, b, ... ) он будет помещен в var).
И код возврата типа ULong.
Обратите внимание! Если вы не вернете 0 при удачном выполнении функции, то REXX ругнется на ошибку выполнения.
function RexxVariablePool(var Pool: ShvBlock): ApiRet; { Указатель на список SHVBLOCK-ов}Параметром для нее служит переменная типа:
PShvBlock = ^ShvBlock; ShvBlock = record shvnext: PShvBlock; { pointer to the next block } shvname: RxString; { Pointer to the name buffer } shvvalue: RxString; { Pointer to the value buffer } shvnamelen: ULong; { Length of the name value } shvvaluelen: ULong; { Length of the fetch value } shvcode: Byte; { Function code for this block } shvret: Byte; { Individual Return Code Flags } end;Ее нужно соответствующим образом заполнить и вызвать RexxVariablePool. Что я и сделал в предлагаемом примере - библиотеке для работы с процессамми. В этой записи следует обратить на поле shvcode, которое может принимать значения:
rxshv_Set = $00; { Set var from given value } rxshv_Fetch = $01; { Copy value of var to buffer } rxshv_DropV = $02; { Drop variable } rxshv_SySet = $03; { Symbolic name Set variable } rxshv_SyFet = $04; { Symbolic name Fetch variable } rxshv_SyDro = $05; { Symbolic name Drop variable } rxshv_NextV = $06; { Fetch "next" variable } rxshv_Priv = $07; { Fetch private information } rxshv_Exit = $08; { Set function exit value }Это команды функции RexxVariablePool. Из них более или менее понятны первые три (задать значение, считать значение, уничтожить переменную - именованый буфер) и $06 - считать следующее по цепочке значение. Таким образом, стем (а точнее именованый буфер) представляет собой цепочку таких блоков. Идентификатором такого буфера является его имя (shvname.strptr). Из каких-то соображений длина и имени стема и его значения повторяется дважды - один раз в составе переменной типа RxString, второй раз в соответствующем поле shvnamelen и shvvaluelen.
Собственно ничего сложного в написании подобной DLL нет, но пример с именованым буфером в Виртуале отсутствует, равно как и подробная документация по написанию DLL для REXX. Существуют также неочевидные моменты - везде в REXX используются null-terminated строки, поэтому нужен глаз да глаз ;), тем более что отлаживать такую библиотеку сложно, так как вызывается она не из EXE-ника...
Теперь о самой библиотеке. Она реализует одну-единственную функцию - ProcList, формат вызова которой:
call RxFuncAdd 'PrcLoadFuncs', 'RXPROCSS', 'PrcLoadFuncs' call PrcLoadFuncs call ProcList 'PROCESS' /* сам вызов */ say 'Процессов 'PROCESS.0 /* там хранится число процессов*/ do i=1 to PROCESS.0 say PROCESS.i /* первое слово - PID процесса, второе его название*/ end
Функцию определения имени процесса по PID и наоборот легко реализовать на самом REXX на основе полученного списка.
В DLL реализована функция PrcLoadFuncs, назначение которой - подключить все функции данной библиотеки. На данный момент таковая только одна, поэтому наличие этой функции необязательно. Если ее закомментировать, то подключение из рекс-скрипта будет выглядеть так:
call RxFuncAdd 'ProcList', 'RXPROCSS', 'ProcList'Программа использует недокументированную функцию DosQuerySysState, за информацию о ней спасибо DrChaos, iN8Malice, zuko, Euxx. zuko - особенно, так как он прислал исходник прямо на виртуале, избавив от необходимости медитации над сишными исходниками. OS2OK - только по его настоянию стал писать эту статью. Большое спасибо joseph за тестирование скриптов и sunlover за помощь в подготовке статьи. Ни в коем случае не претендую на авторство или оригинальность - это чистая компиляция уже проделанной работы.
Что можно усовершенствовать/открыть? Обработку ошибок добавить, у меня ее просто нет. Разобраться как с очередью из функции работать. Команды для RexxVariablePool поизучать. Научиться подключать рексовые длл-ки к паскалевским программам (т.е. обратная задача. Во-первых интересно, во-вторых в отладке поможет).
watchdog1.zip - программа-сторож процессов на рексе. Если какой процесс из списка охраняемых умрет, то она его рестартует. Список процессов получает перенаправлением вывода ps.exe в очередь.
watchdog13.zip - то же, но более продвинутый вариант. Конфиг расширен, процессы могут стартовать или детачится из их рабочих каталогов, и не сами екзешники, а батники, к примеру. Список процессов получает посредством библиотеки, использующей недокументированную функцию OS/2 API.
rxprclst.zip - исходные тексты библиотеки и простой пример ее использования.
Виктор Кустов AKA VikingX
kvv@muka.pptus.ru
Интересные ссылки:
Комментариев к странице: 0 | Добавить комментарий
Редактор: Дмитрий Бан
Оформление: Евгений Кулешов