2017-08-10 56 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