2017-08-10 62 views
0

所以,我有一个C++项目,我想将它放入一个框架中,该框架将充当包装器(用Objective-C/C++编写)到C++代码中,以便我可以稍后在Swift或Objective-C项目中通过简单地将该框架添加到应用程序中来使用它。在Xcode中构建C++项目的包装器框架

我已取得的成就:

  • 创建的所有包装
  • 裸露包装的公共头部在构建阶段
  • 添加一个运行脚本生成阶段简单地复制所有的C++头文件(保持它们的文件目录结构)放入框架的目录中,以便它们可以使用框架在应用程序中使用。我这样做的原因,而不是把它们放在构建阶段的标题栏中,是因为有很多文件和文件夹,这样做需要我将每个标题更改为#include "LocalHeader.h"而不是当前写入的标题如#include "CppRootFolder/Subfolder/Header.h"。此外,我宁愿不这样做,因为我想保持C++文件不变。

问题:

一切似乎构建实际的应用程序时,除了很好地工作时,Xcode就会因错误说,它不能找到该文件结构中的文件。为了说明我的意思,我有以下几点:

  • 为框架的伞文件将#include "CppRootFolder/umbrella.h"(C++的伞文件)
  • 在CppRootFolder/umbrella.h,我有几个#include "CppRootFolder/Subfolder/Header.h"
  • 每一个每个子文件夹中的头文件包含其他头文件,这些头文件从C++代码的根文件夹中引用它们。

我拿到这个:

似乎很清楚,我认为这个问题是编译器需要从C++代码的根文件夹中找到头。因此,在实际的应用程序中,在构建设置中,我将标题搜索路径添加到:$ BUILT_PRODUCTS_DIR/FrameworkName.framework/Headers,这是我将所有标题复制到脚本的位置。但是,构建会失败并产生大量随机错误,而不会识别已定义的类型。

关于如何让这个工作的任何想法?

感谢

UPDATE(日志):

<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

您是在为macOS或iOS开发应用程序吗? CPU架构不一样。你有没有尝试创建一个图书馆项目?或者你是否将C++和Objective-C++代码放在同一个应用程序项目中?是Objective-C++的文件扩展名** .mm **而不是**。m **? – JazzSoft

+0

当你有生成问题总是复制粘贴错误信息。有两个原因:它更容易理解你的问题(我们不依赖你的解释),如果有人有类似的问题,它更容易谷歌它。 –

+0

for iOS,这是一个可可触摸框架项目,添加到一个ios应用程序项目中,C++和obj-C++代码一起在框架项目中,扩展名为.mm for obj-C++ – luis

回答

0

当你写一个包装C++不应该是外部不可见。 因此#include "cppHedarFile.h"不应该在包装器之外访问,否则在Objective C代码中使用C++时会出现错误。

因此,C++头文件不应该有伞头文件。

请提供技术细节:复制粘贴错误消息,你正在看。你对错误的解释可能会引起误解。


您没贴的一切,但这一行:

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

给我后,我是对的。 很可能你是从Objective C文件*.m中包含C++头文件。 对于这样的文件,C++标准头文件不可访问,这就是为什么无法识别int32类型的原因。

就像我在乞讨中写过的一样。当你用C++编写Objective C包装器时,禁止从公共头文件包含C++头文件。 您只能从*.mm文件中获取来自仅由*.mm使用的内部头文件。 这种方式包装工正在做他们的工作,并从包装的用户交付C++。


公开头KXSomeClass.h

@interface KXSomeClass : NSObject 

@property (nonatomic, readonly) BOOL allowed; 

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

@end 

私有头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 

实施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

更新了帖子 – luis

+0

对不起,我想我没有正确地写我做了什么:我的意思是,伞标题包括一个标题(链接到一个.mm文件),这个类中有C++对象,所以在接口(头文件),我包含识别C++对象所需的C++头文件。在接口中的实例变量声明期间,我还可以如何使用C++类? – luis

+0

太棒了!还有一个问题,添加所有这些额外的类别和标题是否会影响性能?这与在实际的公共头文件中使用__cplusplus相比如何? – luis