Почему полиморфные вызовы (такие как слушатель в kauth) имеют анонимные аргументы, а не непрозрачный указатель и функции доступа? - PullRequest
0 голосов
/ 01 ноября 2010

Я смотрю техническую заметку kauth , но это не совсем так. Это более общий вопрос разработки API.

Область для слушателя:

static int MyListener(
    kauth_cred_t   credential,
    void *         idata,
    kauth_action_t action,
    uintptr_t      arg0,
    uintptr_t      arg1,
    uintptr_t      arg2,
    uintptr_t      arg3
);

arg0 ... arg3 зависит от области действия (то есть контекста). Цитировать документацию:

Значение остальных параметров зависит от объема. в последующих разделах ... Например, для области VFS (KAUTH_SCOPE_VNODE) ​​arg1 является ссылкой на vnode (типа vnode_t), с которым работает

Я предполагаю, что есть веская причина для этого дизайна, но я не вижу его. Что если я хочу добавить аргументы позже? Что если я захочу передать типы другого размера (в этом случае uintptr_t определяется по типу unsigned long, но что, если я хочу передать более крупную структуру?).

Пример такого рода проблемы можно увидеть в том же документе:

ВАЖНО: При проверке учетных данных, связанных с запросом, всегда используйте функции доступа, определенные в sys / kauth.h. Будьте особенно осторожны при тестировании на членство в группе. В Tiger пользователь может быть во множестве групп (намного больше, чем традиционный предел 16), и группы могут быть вложенными. Если вы хотите проверить, является ли пользователь членом группы, используйте kauth_cred_ismember_gid.

Если бы я реализовывал функцию API, которую можно вызывать с разными аргументами в разных контекстах, я бы передавал непрозрачный тип (то есть void *) и предоставлял набор функций для извлечения данных из него. Функции меняются с API, будущее.

Итак, кто-нибудь может объяснить, почему авторы выбрали этот дизайн для оставшихся аргументов? Это чисто скорость (в конце концов, пути кода каута невероятно горячие)?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2010

Тип uintptr_t - это целое число без знака, которое гарантированно достаточно большое, чтобы содержать указатель.
Это означает, что целые числа могут быть переданы через интерфейс без каких-либо хлопот, но если у вас есть больший тип, то это также может быть передано по указателю.

Итак, если целые числа являются общим случаем, то вы получаете лучшее из обоих миров:

  • Нет проблем для общего случая и нет сомнений / несоответствий в отношении передачи целых чисел (маскируйте их как указатель или передайте указатель на целое число)
  • Все еще возможно передавать указатели, если вам нужна (ссылка на) большая структура.
0 голосов
/ 01 ноября 2010

Переносимый и расширяемый способ реализовать функцию, которая принимает переменное число аргументов, - объявить ее переменной:

#include <stdarg.h>

static int MyListener (kauth_cred_t   credential, void* idata,
                       kauth_action_t action, ...
{
    va_list ap;
    int count = some_context_dependend_count;
    int j;

    va_start(ap, count); 
    for (j = 0; j < count; j++)
        do_something_with_each_optional_arg (va_arg(ap, uintptr_t); 
    va_end(ap);
    return some_result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...