2010-09-26 4 views
4

J'ai une bibliothèque C++ (.h seulement) qui contient l'implémentation d'une structure de données et je voudrais l'utiliser dans mon application iPhone.Comment faire pour envelopper une librairie C++ dans Objective-C?

Premièrement, j'ai écrit un wrapper dans Objective-C++ en tant que classe qui, à travers la composition, a un ivar de la classe C++. J'ai ensuite été obligé de changer l'extension de la classe wrapper à .mm, et cela semblait bien. Mais alors je dois inclure ce fichier de classe enveloppé dans plusieurs autres fichiers, donc je dois aussi changer leur extension (afin d'éviter une vague d'erreurs de compilation).

Ai-je raison? Existe-t-il un moyen de 'confiner' l'extension .mm à quelques fichiers seulement (et ainsi éviter les conflits de noms, etc.)

EDIT: Quelques informations supplémentaires qui pourraient aider, j'utilise LLVM 1.5 comme compilateur (j'ai remarqué que le nombre d'erreurs de compilation varie de GCC 4.2 à LLVM 1.5 mais je ne suis pas sûr que cela signifie beaucoup, puisque je ne les ai pas toutes regardées)

Répondre

4

Ma recommandation est d'envelopper les C++ bits #ifdefs:

//MyWrapper.h 

#ifdef __cplusplus 
class ComposedClass; 
#endif 

@interface MyWrapper : NSObject 
{ 
#ifdef __cplusplus 
ComposedClass *ptr; 
#endif 
} 

// wrapped methods here... 
@end 

Ceci est une version légèrement boiteux de l'idiome de PIMPL, mais moins de code, et efficace pour cacher C++ - ismes de votre Objective pur Code C Obvioulsy vous devez inclure l'en-tête ComposedClass dans votre MyWrapper.mm.

Si ComposedClass est un type basé sur un modèle, vous devez modifier le premier bloc à

#ifdef __cplusplus 
#include "ComposedClass.h" 
#endif 

au lieu d'utiliser une déclaration avant et puis, bien sûr, utiliser le type basé sur un modèle dans votre classe Objective-C déclaration de variable d'instance.

Cette approche était suggested par Greg Parker, le gourou de l'exécution chez Apple.

+0

Je ne pense pas que ce soit une bonne idée. Tous les fichiers non-C++ qui incluent cet en-tête ne verront pas les membres protégés, et auront donc des tailles différentes pour les classes et des décalages différents pour les variables d'instance. –

+0

@Kristopher, en utilisant le runtime d'Objective-C moderne (qui est la seule option sur iOS), les variables d'instance ne sont pas fragiles, et ce n'est pas un problème. –

+0

@Barry Wark ty Barry cela semble le moyen le plus facile pour moi, mais il semble que je ne suis pas capable d'y parvenir puisque je reçois des erreurs de compilation http://pastebin.com/tp9Zjhss semble que je manque quelque chose, je pensais ils pourraient être des modèles mais dans votre lien ils sont utilisés. – rano

2

Je ne suis pas sûr de comprendre votre question pleinement, mais je pense que la réponse est «oui». Fondamentalement, tout ce qui doit faire référence à la classe wrapper est le code Objective-C++, pas directement C++.

Je vous suggère de limiter votre inclusion de la classe wrapper à la mise en œuvre (aka .cpp ou les fichiers Objective-C++). Ils ne doivent pas faire en sorte que le fichier d'en-tête décrivant les classes qu'ils implémentent deviennent Objective-C++.

Des techniques telles que Pimpl idiom peuvent aider à isoler les utilisateurs de votre classe du fait qu'elle est implémentée en partie dans Objective-C++.

+0

+1 Je tiens à limiter la cascade en incluant juste dans les fichiers '.mm' – rano

+0

@rano - On dirait que votre problème est le problème inverse de celui auquel j'ai décrit la solution. Et il semble que Objective-C/C++ n'a pas le concept d'une implémentation séparée de la définition de classe. Cela rend le travail beaucoup plus difficile et nécessite une meilleure compréhension que j'ai de Objective-C/C++. – Omnifarious

+0

Je ne comprends pas votre point maintenant, objectif-C/C++ fournit une séparation pour l'interface/l'implémentation d'une classe – rano

4

Tout code qui inclut un fragment C++ (aussi petit soit-il) doit être compilé avec Objective-C++ (et donc figurer dans un fichier .mm). Si vous souhaitez réduire le nombre de fichiers .mm, vous devez intégrer la fonctionnalité de votre code C++ dans une classe Objective-C afin que l'interface publique de cette classe (son fichier .h) se compose uniquement de code Objective-C. Cela signifie que la classe wrapper ne doit pas contenir un ivar public d'un type C++. Si c'est une approche réalisable si votre lib C++ consiste seulement en une structure de données, je ne sais pas.

Notez que AFAIK LLVM 1.5 n'inclut pas encore le support C++ (seul LLVM 2.0 le fait). AFAIK, lorsque vous sélectionnez LLVM 1.5, Xcode bascule automatiquement sur GCC pour tous les fichiers C++/Objective-C++.

+0

+1 pour les éclaireurs de dilemme du compilateur:) – rano

1

Ma solution préférée est cette macro déclaration avant:

#define FORWARD(cpp_class) struct cpp_class; typedef struct cpp_class cpp_class;

FORWARD(SomeCppClass); 

@interface MyObjcWrapper : NSObject { 
    SomeCppClass *ptr; 
} 

Alors MyObjcWrapper.h est sûr d'inclure dans Objective-C et les fichiers Objective-C++.

Ceci est tiré d'un article de blog utile que j'ai vu il y a quelques années - je n'arrive pas à le trouver maintenant.

Questions connexes