D3 Reference Manual

Index | Help

Поиск по страницам

Разделы / С-функции / Использование С-функций

Использование С-функций

Библиотечный формат

Общие сведения по использованию

Обработка строк

Установка среды

Клавиша break

Обработка общих прерываний D3

Традиционная обработка сигналов

Пример

Из языка программирования C доступны все функциональные средства системы D3. Это возможно благодаря набору функций и макросов, описанных в заголовочном файле CPuser.h

Библиотечный формат

Функции в библиотеке имеют следующую общую структуру:

{rc = } _CP_xxx( { arg0 {, arg1 {, ... }}});

где:

_CP_xxx - общая структура имени. Во избежание путаницы с именами в стандартных библиотеках имя всегда имеет приставку "_CP_" и метку, состоящую только из строчных букв (как в "_CP_execute"). Для макросов используется та же самая модель, но их метки состоят из заглавных букв (как в "_CP_SLEN").

arg0-argi - аргументы.

rc - код результата. В случае ошибки этот результат равен "-1", а глобальная переменная "_CP_errno" содержит один из следующих кодов:

PE_NFILE Слишком много открытых файлов
PE_ACCESS Обращение к файлу невозможно
PE_TRUNC Запись усечена во время чтения
PE_NOSPACE Предоставление рабочей памяти невозможно
PE_LOCK Запись заблокирована
PE_INVAL Неправильный вызов
PE_NONUM Не число
PE_BADF Файл не открыт
PE_MISSING Файл не обнаружен
PE_CONV Ошибка преобразования
PE_BADATTR Неправильный атрибут
PE_TMOUT Блокировка по времени на вводе
PE_TAPE Ошибка ленты
PE_PROC Ошибка чтения процедуры Proc
PE_EOF Конец файла/записи
PE_CALLMAIN Попытка вызова главной программы в качестве подпрограммы
PE_NOTROOT Неправильная переменная root
PE_ILL_KEY Неправильный оператор key
PE_LONG_STR Слишком длинная строка для заголовка
PE_LEVEL Вход в отладчик
PE_DEBUG Вход в отладчик
PE_BAD_PARAMS Слишком много параметров вызова
PE_LOAD_ERR Загрузка подпрограммы FlashBASIC невозможна
PE_END_LIST Конец списка выбранных записей select
PE_GETSEND Неправильный pib при операциях get/send
PE_MISCERR Какая-либо ошидка подключения logon
PE_INIT Виртуальная машина не загружена или не подсоединена
PE_BADUSER Неправильный идентификатор или пароль пользователя
PE_BADMD Неправильное имя счета или пароль
Общие сведения по использованию

Чтобы воспользоваться этой библиотекой, пользователь в начале своей программы на языке C вызывает функцию "_CP_logon()" для подключения к виртуальной машине D3. В ходе выполнения этого вызова происходит то же самое, что и при обычной операции подключения в системе D3, но без каких-либо приглашений пользователю. Следует отметить, что при этом не выполняется ни пользовательский макрос, ни макрос MD. После подключения пользователь имеет полный доступ к базе данных D3. И, наконец, по завершении программы на языке C пользователь должен вызвать функцию "_CP_logoff()" для отключения от системы D3.

Обработка строк

Стандартный тип строки C недостаточен для обработки динамических по природе строк системы D3, поэтому был создан гибридный тип данных CPSTR. Этот тип данных обеспечивает назначение, освобождение и изменение размера строк с гораздо большей производительностью, чем в случае использования для C-строк функций "malloc" и "free". Внутренняя структура CPSTR зарезервирована, и никакого прямого обращения к ней не должно быть. Несоблюбение этого правила наверняка гарантирует несовместимость с будущими версиям системы. CPSTR имеет следующую структуру:

  • Заголовок (header) - только для внутреннего использования - не изменять.
  • Строка (string) - массив символов, содержащий действительную строку;
  • Конечный символ (terminator) - один символ, используемый как конечный;
  • Основание (footer) - только для внутреннего использования - не изменять.

Для доступа ко всем нужным частям структуры CPSTR предоставляются следующие макросы:

  • _CP_SLEN(s) возвращает текущую длину строки. Эта длина не включает символ окончания (terminating character).
  • _CP_SADDR(s) возвращает указатель "char *" на действительную строку данных, которая может заканчиваться или не заканчиваться нулевым байтом (0x00). Cледует отметить, что этот "char *" НЕ ДОЛЖЕН передаваться C-функции "free()" или любой другой C-функции, которая может попытаться выполнить функцию "free()" с этим "char *".

Назначение строк CPSTR осуществляется с помощью специальных программ назначения ("allocation routines"). Строки CPSTR не должны назначаться с помощью C-функции "malloc". Имеющиеся программы назначения устанавливают необходимые флаги и работают гораздо более эффективно, чем "malloc". Следует отметить, что эти программы создают динамические структуры, которые должны освобождаться с помощью программ, указанных ниже.

_CP_str_alloc(l) возвращает CPSTR длины "l". Часть строки, где действительно находятся ее данные, не определена и может содержать "мусор".

_CP_mkstrl(int l,char *s) возвращает CPSTR из C-строки "s" длины "l". Сама строка данных CPSTR будет содержать копию данных C-строки.

_CP_mkstr(char *s) возвращает CPSTR из C-строки "s" с конечным нулевым байтом (0x00). Сама строка CPSTR будет содержать копию данных C-строки.

_CP_str_realloc(CPSTR **s, int l) изменяет размер строки CPSTR "s".

_CP_str_free(CPSTR ** s) освобождает строку "s".

Следует отметить, что когда выполняется вызов "_CP_logoff", все строки CPSTR остаются действительными, но уже не могут быть переданы "_CP_"-программам.

Пользователь должен соблюдать осторожность с символом окончания. Любая "_CP_"-программа может модифицировать символ окончания. Следовательно, для передачи самой строки в стандартную программу Unix пользователь должен использовать макрос "_CP_TERM()", чтобы строка CPSTR заканчивалась нулевым байтом (0x00).

Следует отметить, что строки должны освобождаться только тогда, когда пользователь полностью закончил работу с ними. Необходимое изменение размера строк производится "_CP_"-программами автоматически. Если, например, процесс считывает данные в буфер с помощью повторных вызовов "_CP_read", размер буфера будет динамически изменяться при каждом вызове "_CP_read" для размещения считанных данных.

Установка среды

Для упрощения преодоления различий между стандартным поведением программ Unix и стандартным поведением программ D3, предоставляются два вида вызова, которые устанавливают либо "среду D3", либо "среду Unix".

_CP_pick_env() настраивает приложение на "среду D3". Когда используется эта установка, весь терминальный ввод и вывод должен осуществляться только через программы D3.

_CP_unix_env() настраивает приложение на стандартную "среду Unix". При такой установке весь терминальный ввод и вывод должен осуществляться прямо из "C". Программа не должна выполнять ("execute") или вызывать ("call") никакие программы D3, которые осуществляют вывод через D3 с помощью операторов "crt" или "print".

Во время начальной операции подключения к системе D3 вызывается функция "_CP_pick_env()". После этого пользователь может использовать указанные подпрограммы для изменения среды по мере необходимости. Следует, однако, помнить о том, что эти функции достаточно дороги и должны использоваться только в случаях, когда изменение среды абсолютно необходимо. Для обеспечения правильной работы интерпретатора команд Unix система автоматически вызыает функцию "_CP_unix_env(), когда пользователь отключается от виртуальной машины D3.

Клавиша break

После подключения к системе D3 клавиша "break" по умолчанию повышает уровень или переводит в отладчик, что в системе D3 является стандартом. Но это поведение клавиши можно изменить с помощью следующих вызовов:

_CP_unix_break() устанавливает режим, при котором нажатие на клавишу "break" вызывает отключение от системы D3 и останов программы на языке C посредством вызова "exit()". Таким образом имитируется стандартное поведение клавиши "break" в приложении Unix.

_СP_pick_break() вызывает такое же поведение клавиши "break", как в системе D3.

Обработка общих прерываний D3

Другие прерывания системы D3 (например, сообщения) не могут обрабатываться с помощью маски, но при их свершении могут быть обнаружены путем проверки переменной "_CP_interrupt". Этот адрес "int" содержит ту же самую информацию, которую возвращает функция "system(37)" BASIC. Однако при программировании на C просмотр переменной "_CP_interrupt" гораздо более эффективен.

Традиционная обработка сигналов

Библиотеки D3 широко используют обработку сигналов. Вследствие этого настоятельно НЕ рекомендуется перепрограммирование сигналов в приложениях C с помощью C-программ D3. Если, однако, это абсолютно необходимо, должны соблюдаться следующие правила:

  • При вызове "_CP_logon" все сигналы перенаправляются обработчику сигналов D3.
  • При вызове "_CP_logoff" все сигналы перенаправляются программам Unix с значениями параметров, используемыми по умолчанию. Следует отметить, что при этом не обязательно возвращаются значения параметров, которые были перед вызовом "_CP_logon".
  • Сигнал SIGUSR2 не должен перепрограммироваться никогда, т.к. от используется системой D3 для отключения ("logging off") и посылки сообщений.

Т.к. прерывания могут происходить в критичном коде, пользователь не должен вызывать "_CP_"-функции в обработчиках прерываний.

Пример

Следующая программа печатает имена всех пользователей в файле users.

#include "CPuser.h"
main()
{
    CPSTR * machine = _CP_mkstrl("pick0",2); /* default */
    CPSTR * user = _CP_mkstrl("dm",2);
    CPSTR * md = _CP_mkstrl("dm",2);
    CPSTR * filename = _CP_mkstrl("users",5);
    int     fd = -1;
    int     sl = -1; /* Активизация списка */
    CPSTR * item_id = _CP_str_null;
   
    /* Подключение к "pick0" как "dm" в "dm md" */
    if (_CP_logon(machine, user, _CP_str_null, 
                             md, _CP_str_null, -1, 0) < 0)
    {
         printf("Logon error %d\n", _CP_errno);
    }
    /* Окончание работы с машиной, пользователем и md */
    _CP_str_free(machine);
    _CP_str_free(user);
    _CP_str_free(md);
    /* Клавиша break должна прекращать выполнение программы */
    _CP_unix_break();
    /* Открытие файла users с дескриптором файла fd */
    if (_CP_open(&fd, _CP_str_null, filename) < 0)
    {
         _CP_logoff();
         printf("Открытие файла users невозможно \n");
    }
    /* Окончание работы с именем файла */
    _CP_str_free(filename);
    /* Выборка из файла "users" и запоминание списка в дескрипторе списка sl */
    _CP_select(fd, &sl, 0);
    /* Переход на ввод/вывод Unix для использования printf */
    _CP_unix_env();
    /* Повторное считывание ключей записей и их печать в
       виде списка */
    /* Следует отметить, что ключ (item_id) повторно передается
       функции "_CP_readnext". Каждый раз в случае необходимости
       функция _CP_readnext изменяет размер CPSTR и записывает 
       следующий ключ записи в эту строку CPSTR.             */
    while (_CP_readnext(&item_id, &sl, 0, 0) >= 0)
    {
         _CP_TERM(item_id); /* terminate for printf */
         printf("%s\n", _CP_SADDR(item_id));
    }
  
    /* Окончание работы с item_id */
 
    _CP_str_free(item_id);
    /* Отключение и возвращение */
    _CP_logoff();
    return 0;
}