2010-11-01 9 views
0

Je regarde le kauth tech note, mais ce n'est pas à ce sujet spécifiquement. C'est plus une question générale de conception d'API.Pourquoi les appels polymorphes (tels que l'écouteur dans kauth) ont-ils des arguments anonymes plutôt qu'un pointeur opaque et des fonctions d'accès?

Le champ d'application pour un auditeur est:

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 
); 

Le arg0 ... arg3 dépendent de la portée (à savoir le contexte). Pour citer la documentation:

La signification des paramètres restants dépend de la portée. dans les sections suivantes ... Par exemple, pour le champ VFS (KAUTH_SCOPE_VNODE), arg1 est une référence à la vnode (de type vnode_t) qui est en cours opérés

Je suppose qu'il ya une bonne raison pour cela conception, mais je ne peux pas le voir. Que faire si je veux ajouter des arguments plus tard? Que faire si je veux passer en types de tailles différentes (dans ce cas, uintptr_t est typedefed à unsigned long mais si je voulais passer dans une structure plus grande?).

Un exemple de ce genre de question peut être vu dans le même document:

IMPORTANT: Lors du contrôle des informations d'identification associés à une demande, utilisez toujours les fonctions accesseurs définies dans sys/kauth.h. Soyez particulièrement prudent lors des tests d'appartenance à un groupe. Dans Tiger un utilisateur peut être dans beaucoup de groupes (beaucoup plus que la limite traditionnelle de 16) et les groupes peuvent être imbriqués. Si vous voulez tester si un utilisateur est membre d'un groupe, utilisez kauth_cred_ismember_gid.

Si j'exécutaient une fonction API qui peut être appelée avec des arguments différents dans des contextes différents, je passerais dans un type opaque (à savoir un void *) et de fournir un ensemble de fonctions pour extraire les données. Les fonctions changent avec l'API, futureproof. Donc, quelqu'un peut-il donner un aperçu de la raison pour laquelle les auteurs ont pu choisir cette conception pour les arguments restants? Est-ce purement la vitesse (les chemins de code de kauth sont incroyablement chauds après tout)?

Répondre

0

Le type uintptr_t est un entier non signé qui est garanti assez grand pour contenir un pointeur comme bien.
Cela signifie que les entiers peuvent être passés à travers l'interface sans aucun tracas, mais si vous avez un type plus grand, cela peut également être passé par un pointeur.

Donc, si les entiers sont le cas commun, alors vous obtenez le meilleur des deux mondes:

  • Pas de problème pour le cas commun et aucun doute/incohérences sur les entiers passant (les masquerade comme un pointeur, ou passer un pointeur sur l'entier)
  • Il est toujours possible de passer des pointeurs si vous avez besoin (d'une référence à) d'une structure plus grande.
0

La manière portable et extensible pour mettre en œuvre une fonction qui prend un nombre variable d'arguments est de déclarer VARIADIC:

#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; 
}