2010-11-17 24 views
8

我想在Objective-C中做一個包裝器,所以我不必在庫類之外編寫C++。爲C++庫製作一個Objective-C包裝器

圖書館主文件是LLAHProcessor.h .cpp

我的包裝是LLAHProcessorWrapper.h .mm

它編譯罰款,但是當我添加LLAHProcessorWrapper到其他類,(比方說一個的UIView)作爲成員變量,我得到數百個錯誤,如:

#include <map> : Map no such a file or directory 

,並在每C++類/結構:

Expected specifier-qualifier list before ClassName 

就像編譯器不識別C++代碼一樣。

我想知道我在這裏錯過了什麼。 它是否必須是事實我添加到Xcode目標屬性:?

Other Link Flags : -lstdc++ -lz 

或者我可能需要在這裏添加新的標誌?

在此先感謝

+1

「LLAHProcessorWrapper.h」不包含任何C++代碼。 'LLAHProcessor.h'應該在'.mm'中導入。文件,不在'.h'文件中。是你做的嗎? – 2010-11-17 12:20:25

+0

你在項目中也有.m文件嗎? – 2010-11-17 12:24:18

+0

@Chris我有很多.m文件。這是一個相當大的計劃。 – nacho4d 2010-11-17 12:26:31

回答

6

你的問題是,.m文件被編譯爲C而不是C++。因此,當編譯器在編譯.m文件時遇到任何C++甚至在頭文件中時,它都會變成barf。

毫無疑問,你必須在你的頭文件中放置一些C++,因爲你的Objective C對象包裝了一個C++對象,但是有一些解決方法。一種方法是使用指向C++對象的指針,並使用定義用於C++(和Objective-C++)但不適用於C(或Objective-C)的便利預處理器define __cplusplus,例如

// LLAHProcessorWrapper.h 

#if defined __cplusplus 
class MyCPPClass; // forward class declaration 
#else 
typedef struct MyCPPClass MyCPPClass; // forward struct declaration 
#endif 

@interface MyOCClass : NSObject 
{ 
@private 
    MyCPPClass* cppObject; 
} 

// methods and properties 

@end 

因爲你永遠不取消引用cppObject的.mm文件以外的成員也沒關係,你從來沒有提供該結構的完整定義。

你會分別在-init-dealloc的指針newdelete。您可以在LLAHProcessorWrapper.mm中包含完整的C++類聲明。

+1

對任何人都適用:我在'LLAHProcessorWrapper.h'中仍然有'#include「MyCPPClass.h」''被抓住了。它應該在'LLAHProcessorWrapper.mm'中。 – Ross 2011-05-20 13:22:37

+0

我想我們現在可以使用類延伸?也許更好的方法? – Ahmed 2013-02-10 04:38:28

4

所有你需要做的是創造一個.mm爲你所做的一切,以及編譯器應該照顧一切。

需要注意的是,在.h文件中有任何與C++相關的東西是不安全的,因爲它們可以/將被其他Objective-C唯一文件導入,然後一切都會崩潰。這裏的主要問題是,除非每個.m文件都重命名爲Objective-C++ .mm文件,否則不能直接將C++類型定義爲Objective-C包裝類的實例變量。

解決的辦法是在頭文件中定義實例變量爲void*,並通過執行文件中的類型轉換來訪問它們。最簡單的解決方案是使用一個私有屬性來訪問實例變量,該私有屬性可用於類型轉換。在Foo.h定義

示例代碼假設Foo是一個C++類:

// FooWrapper.h 
#import <Foundation/Foundation.h> 

@interface FooWrapper : NSObject { 
@private 
    void* foo; 
} 
// Actual wrapper API for Foo… 
@end 


// FooWrapper.mm 
#import "FooWrapper.h" 
#include <map> 
#include "Foo.h" 

@interface FooWrapper() 
@property(nonatomic, assign) Foo* foo; 
@end 

@implementation FooWrapper 
-(Foo*)foo { 
    return (Foo*)foo; 
} 
-(void)setFoo:(Foo*)aFoo { 
    foo = (void*)aFoo; 
} 
// Implementation of actual API for Foo… 
@end 
0

在其中要參考LLAHProcessorWrapper任何報頭(.h)文件,使用正向類定義,而不是進口,像這樣:

@class LLAHProcessorWrapper; 
@interface SomeView : UIView { 
    LLAHProcessorWrapper *wrapper; 
} 

,並確保相應的實現文件#include LLAHProcessorWrapper.h#import LLAHProcessorWrapper.h

在其中#include#import你的頭必須.mm作爲其後綴如果LLAHProcessorWrapper.h任何東西在整個包括樹有任何C++的語法在所有的任何實現文件。這樣,有一個.mm文件傾向於意味着代碼庫的大部分必須將其文件重命名爲.mm