2011-03-14 2 views
4

Je travaille avec une interface de bibliothèque héritage C (en C++) qui expose des pointeurs opaques commeC pointeur opaque Gotchas

typedef void * OpaqueObject 

Dans la bibliothèque:

OpaqueObject CreateObject() 
{ 
    return new OurCppLibrary::Object(); 
} 

Bien sûr, ne fournit absolument pas type de sécurité pour les clients de cette bibliothèque. Devrait changer le typedef d'un pointeur vide au pointeur de structure fonctionne exactement la même chose, mais fournir une petite quantité de sécurité de type?

typedef struct OpaqueObjectInternal_ *OpaqueObject 
// OpaqueObjectInternal_ is NEVER defined anywhere in client or library code 

Y at-il des problèmes d'alignement ou d'autres trucs que je dois à vous soucier maintenant que je montre explicitement à une structure, même si je ne suis vraiment pas en montrant un?

+3

Il n'y a pas d'opérateur appelé 'nouveau' dans ** C ** !! – Mahesh

+2

@Mahesh: Je pense que l'OP enveloppe une bibliothèque C en C++; le 'new' se déroule en C++ (déduit du qualificatif' OurCppLibrary') – fbrereto

+2

'void *' est tout à fait logique en tant qu'objet opaque - votre fin de choses ne va pas déranger l'objet, et ils savent quoi fais avec. Si quelque chose, en faire un «void *» le rend plus sûr, tant que vous l'utilisez avec leur API comme décrit. – James

Répondre

7

Il n'y a pas de gotcha; cette forme est préférée exactement à cause de la sécurité du type.

Non, l'alignement n'est pas un problème ici. Le pointeur lui-même a un alignement connu, et l'alignement de l'objet sur lequel il pointe ne concerne que l'implémentation de la bibliothèque, pas l'utilisateur.

1

La première chose à considérer avec votre cours suggéré est ce que vous communiquez aux autres qui peuvent avoir à maintenir le code que vous écrivez. Au-dessus de toutes les autres choses, les objets opaques sont le moyen C d'indiquer à l'utilisateur d'une bibliothèque que le mainteneur de la bibliothèque ne garantit absolument pas l'implémentation d'un objet autre que l'utilisation des fonctions documentées. En supprimant le vide * que vous annoncez au monde, "je déclare cette implémentation qui était autrefois opaque pour être stable." Ce n'est peut-être pas ce que vous voulez. Deuxièmement, IMHO que vous proposez est le genre de demi-solution qui ne satisfait personne, une meilleure approche consiste à développer une classe d'emballage. Cela a l'avantage supplémentaire de vous permettre d'envelopper les fonctions init et destroy qui accompagnent inévitablement les objets opaques de style C dans les constructeurs et les destructeurs de votre classe. Cela vous permettra de fournir la gestion des ressources ainsi que la sécurité de type à vos clients sans beaucoup plus de travail.

+1

Je ne comprends pas pourquoi le pointeur struct n'est pas opaque. Il n'y a pas de définition de la structure à laquelle le client peut accéder (ou l'implémentation, d'ailleurs.) En ce qui concerne une classe wrapper, c'est pour un consommateur C. –

+0

Il semblerait que je sois confus par le fait que l'exemple utilise des constructions C++ le titre dit C++ .De plus, je recommande de ne pas nommer la structure OpaqueObjectInternal_ Internal et le trait de soulignement final sont des conventions communes qui indiquent des implémentations privées.Ne pas lire les commentaires assez soigneusement m'a amené à croire que cette structure était l'implémentation interne pas le pointeur opaque Il y a peut-être une leçon pour nous deux ici ;-) – ltc

+0

Quelqu'un a édité le titre de C à C++. Que nommez-vous la structure? Il existe une structure différente pour chaque type que l'interface C connaît. –

2

En fait, une classe C++ est également une structure C. Ainsi, vous pouvez simplement faire ceci:

struct Object; 
struct Object* Object_Create(void); 

Et, l'emballage C dans la bibliothèque ainsi:

struct Object* Object_Create(void) 
{ 
    return new Object; 
} 

Un appel de méthode pourrait ressembler à ceci:

uint32_t Object_DoSomething(struct Object* me, char * text) 
{ 
    return me->DoSomething(text); 
} 

J'ai essayé et je ne vois aucun inconvénient.