2017-08-10 1 views
0

Donc, j'ai un projet C++ que je veux mettre dans un framework qui va agir comme un wrapper (écrit en Objective-C/C++) au code C++, de sorte que je peut ensuite l'utiliser dans un projet Swift ou Objective-C en ajoutant simplement le cadre à l'application.Construire un framework wrapper pour le projet C++ dans Xcode

Ce que j'ai accompli jusqu'à présent:

  • a créé tous les emballages
  • Exposed têtes publiques de l'emballage dans la phase de construction
  • Ajouté un script d'exécution dans la phase de construction simplement copier tous les en-têtes C++ (en gardant leur structure de répertoire de fichiers) dans le répertoire du framework, de sorte qu'ils sont disponibles pour l'application utilisant le framework. La raison pour moi de le faire et de ne pas les mettre dans le champ des en-têtes de la phase de construction est parce qu'il y a beaucoup de fichiers et de dossiers et que cela obligerait à changer tous les en-têtes à #include "LocalHeader.h" plutôt que comment il est actuellement écrit comme #include "CppRootFolder/Subfolder/Header.h". Aussi je préférerais ne pas le faire parce que je veux garder les fichiers C++ inchangés.

Le problème:

Tout semble bien fonctionner sauf que lors de la construction de l'application réelle, XCode erreur en disant qu'il ne peut pas trouver les fichiers dans la structure du fichier. Pour illustrer ce que je veux dire, je donne les résultats suivants:

  • Le fichier parapluie pour le cadre sera #include "CppRootFolder/umbrella.h" (C++ fichier parapluie)
  • Dans CppRootFolder/umbrella.h, j'ai plusieurs #include "CppRootFolder/Subfolder/Header.h"
  • Chacun des en-têtes à l'intérieur de chaque sous-dossier incluent d'autres en-têtes les référençant depuis le dossier racine du code C++.

Mon opinion à ce sujet:

Il me semble clair que la question est que le compilateur a besoin de trouver les en-têtes à partir du dossier racine du code C++. Ainsi, dans l'application actuelle, dans les paramètres de construction, j'ajoute un chemin de recherche d'en-tête à: $ BUILT_PRODUCTS_DIR/FrameworkName.framework/Headers, où j'ai copié tous les en-têtes avec le script. Cependant, la construction échoue et produit beaucoup d'erreurs aléatoires ne reconnaissant pas les types qui sont déjà définis.

Des idées sur comment je peux faire fonctionner ça?

Merci

MISE À JOUR (Journaux):

<module-includes>:1:9: note: in file included from <module-includes>:1: 
#import "Headers/Box2D.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17: 
#import "World.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10: 
#import "Box2D/Box2D.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:34:10: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:34: 
#include "Box2D/Common/b2Settings.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Settings.h:153:8: error: must use 'struct' tag to refer to type 'b2Version' 
extern b2Version b2_version; 
    ^
<module-includes>:1:9: note: in file included from <module-includes>:1: 
#import "Headers/Box2D.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17: 
#import "World.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10: 
#import "Box2D/Box2D.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:35:10: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:35: 
#include "Box2D/Common/b2Draw.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Draw.h:22:10: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Draw.h:22: 
#include "Box2D/Common/b2Math.h" 
     ^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Math.h:28:31: error: unexpected type name 'int32': expected expression 
     int32 ix = *reinterpret_cast<int32*>(&x); 
+0

Développez-vous l'application pour macOS ou iOS? Les architectures de CPU ne sont pas identiques. Avez-vous essayé de créer un projet de bibliothèque? Ou avez-vous mis du code C++ et Objective-C++ dans le même projet d'application? Est-ce que les extensions de fichier **. Mm ** au lieu de **. M ** pour l'Objective-C++? – JazzSoft

+0

lorsque vous avez un problème de build TOUJOURS copier le message d'erreur coller. Il y a deux raisons: il est plus facile de comprendre votre problème (nous ne comptons pas sur votre interprétation) et si quelqu'un a un problème similaire, il est plus facile de le google. –

+0

pour iOS, il s'agit d'un projet de cadre tactile de cacao, qui est ajouté à un projet d'application ios, C++ et code obj-C++ sont ensemble dans le projet cadre, les extensions sont .mm pour obj-C++ – luis

Répondre

0

Lorsque vous écrivez un wrappers C++ ne doivent pas être visibles à l'extérieur. Donc, #include "cppHedarFile.h" ne devrait pas être accessible en dehors de l'encapsuleur, sinon vous aurez des erreurs sur l'utilisation de C++ dans le code Objective C.

Il ne devrait donc pas y avoir de fichier d'en-tête parapluie pour les en-têtes C++.

Veuillez fournir les détails techniques: copier le message d'erreur de pâte que vous voyez. Votre interprétation de l'erreur peut être trompeuse.


Vous ne l'avez pas coller tout, mais cette ligne:

/Box2D.framework/Headers/Box2D/Common/b2Math.h:28:31: error: unexpected type name 'int32': expected expression 
    int32 ix = *reinterpret_cast<int32*>(&x); 

Donne-moi une biche que je ne me trompe pas. Très probablement, vous incluez les en-têtes C++ du fichier Objective C *.m. Pour un tel fichier, les en-têtes standard C++ ne sont pas accessibles, c'est pourquoi le type int32 n'est pas reconnu.

Comme je l'ai écrit à la prière. Lorsque vous écrivez un wrapper Objective C autour de C++, les en-têtes C++ des en-têtes publics sont interdits. Vous pouvez le faire seulement former le fichier *.mm pour des en-têtes internes qui sont seulement utilisés par *.mm. De cette façon, les wrappers font leur travail et transmettent C++ à l'utilisateur de wrapper.


Exemple

tête publique KXSomeClass.h:

@interface KXSomeClass : NSObject 

@property (nonatomic, readonly) BOOL allowed; 

- (NSUInteger)someAction:(NSString *)s; 

@end 

tête privée KXSomeClass+Internal.h

// this header is used only by wrappers 
#import "KXSomeClass.h" 
#include <memory> 
@interface KXSomeClass() 

- (instancetype)initWithNativeSomeClass:(const std::shared_ptr<SomeClass>&)nativeObject; 

@end 

mise en œuvre KXSomeClass.mm

#import "KXSomeClass+Internal.h" 

@interface KXSomeClass() 
@property (assign, nonatomic) std::shared_ptr<SomeClass> native; 
@end 

#import "KXSomeClass+Internal.h" 
#include "cpp/SomeClass.h" 

@implementation CSCapability 

- (instancetype)initWithNativeSomeClass:(const std::shared_ptr<SomeClass>&)nativeObject 
{ 
    if (self = [super init]) { 
     _native = nativeObject; 
    } 
    return self; 
} 

- (NSUInteger)someAction:(NSString *)s 
{ 
    return _native->SomeAction(s.UTF8String); 
} 

- (BOOL)allowed 
{ 
    return _native->Allowed(); 
} 

@end 
+0

mis à jour le poste – luis

+0

désolé, je pense que je n'ai pas correctement écrit ce que j'ai fait: ce que je voulais dire est que l'en-tête parapluie est inclus un en-tête (lié à un fichier .mm) et cette classe a des objets C++ l'interface (en-tête), j'inclus les en-têtes C++ nécessaires pour reconnaître les objets C++. Sinon, comment puis-je utiliser les classes C++ pendant la déclaration de variable d'instance dans l'interface? – luis

+0

génial! une question de plus, est-ce que l'ajout de toutes ces catégories et en-têtes supplémentaires compromet les performances? Comment cela se compare-t-il à l'utilisation de __cplusplus dans les en-têtes publics réels? – luis