Каждая таблица может определять свою собственную функцию обратного вызова, которая подменяет обычную обработку параметров, определенных в этой таблице. Вместо нее функция обратного вызова вызывается для каждого обнаруживаемого параметра. Параметры, определяемые в других таблицах параметров (включая таблицы, вложенные в таблицу, определяющую обратный вызов), обрабатываются с использованием обычных правил, если только в других таблицах не будут определены свои собственные обратные вызовы.
Обратные вызовы можно определять только в первом элементе таблицы параметров. Если этот элемент определяет обратный вызов, член argInfo
будет иметь значение POPT_ARG_CALLBACK
, a arg
будет указывать на функцию обратного вызова. Член descrip
может представлять любое значение указателя, и передается в обратный вызов каждый раз во время его инициирования, открывая доступ к любым произвольным данным. Все остальные члены структуры struct poptOption
должны иметь нулевое значение или NULL
.
Во время обработки параметров обратный вызов можно инициировать в трех точках: до начала обработки, при нахождении параметра в таблице для данного обратного вызова и после завершения обработки. Это дает библиотекам возможность инициализировать любые необходимые им структуры (включая данные, определяемые членом descrip
), и выполнять любые служебные действия, которые могут понадобиться после завершения обработки (например, очищать динамическую память, выделенную для члена descrip
). Они всегда вызываются при нахождении параметра, однако в таблице параметров необходимо указать, что их нужно вызывать в двух других местах. Чтобы сделать это, значения POPT_CBFLAG_PRE
или POPT_CBFLAG_POST
(или оба) должны объединяться битовым "ИЛИ" со значением POPT_ARG_CALLBACK
, присвоенным члену arg
структуры, которая определяет обратный вызов.
Далее показан прототип, который следует использовать для определения функции обратного вызова:
void callback(poptContext con, enum poptCallbackReason reason,
const struct poptOption * opt, const char * arg,
const void * data);
Первый параметр представляет содержимое, синтаксический анализ которого будет выполнен во время инициирования обратного вызова. Следующим параметров является POPT_CALLBACK_REASON_PRE
, если обработка параметра еще не началась, POPT_CALLBACK_REASON_POST
, если обработка параметров завершена, или POPT_CALLBACK_REASON_OPTION
, если в таблице для данного обратного вызова был обнаружен параметр. Если этот параметр является последним, то аргумент opt будет указывать на элемент таблицы параметров для обнаруженного параметра, а аргумент arg
будет указывать на строку, определяющую аргумент для данного параметра. Если ожидается аргумент, не представленный в виде строки, обратный вызов будет отвечать за проверку типа и преобразование аргумента. Последний параметр для обратного вызова, data
, представляет собой значение поля descrip
в элементе таблицы параметров, который задает обратный вызов.
Ниже показан пример библиотеки, которая использует вложенную таблицу popt
и обратные вызовы для синтаксического анализа некоторых параметров командной строки. Структура данных инициализируется до начала синтаксического анализа командной строки, а затем отображаются последние значения.
1: /* popt-lib.с */
2:
3: #include
4: #include
5:
6: struct params {
7: int height, width;
8: char*fg,*bg;
9: };
10:
11: static void callback(poptContext con,
12: enum poptCallbackReason reason,
13: const struct poptOption * opt,
14: const char * arg,
15: const void * data);
16:
17: /* Здесь сохраняются переменные, которые прошли синтаксический анализ. Обычно
18: глобальные переменные использовать не рекомендуется, зато работать с ними проще.*/
19: struct params ourParam;
20:
21: struct poptOption libTable[] = {
22: { NULL, '\0',
23: POPT_ARG_CALLBACK | POPT_CBFLAG_PRE | POPT_CBFLAG_POST,
24: callback, '\0', (void *) &ourParam, NULL },
25: { "height", 'h', POPT_ARG_STRING, NULL, '\0', NULL, NULL },
26: { "width", 'w', POPT_ARG_STRING, NULL, '\0', NULL, NULL },
27: { "fg", 'f', POPT_ARG_STRING, NULL, '\0', NULL, NULL },
28: { "bg", 'b', POPT_ARG_STRING, NULL, '\0', NULL, NULL },
29: { NULL, '\0', POPT_ARG_NONE, NULL, '\0', NULL, NULL }
30: };
31:
32: static void callback(poptContext con,
33: enum poptCallbackReason reason,
34: const struct poptOption * opt,
35: const char * arg,
36: const void * data) {
37: struct params * p = (void *) data;
38: char * chptr = NULL;
Читать дальше