2010-09-26 58 views
4

我有一個C++庫(僅限.h),它包含數據結構的實現,我想在我的iPhone應用程序中使用它。如何在Objective-C中包裝C++庫?

首先,我在Objective-C++中編寫了一個封裝器,作爲一個類,通過組合,它擁有一個C++類的ivar。然後我'有義務'將包裝類的擴展名更改爲.mm,看起來很好。但之後我必須將這個包裝的類文件包含到其他幾個文件中,所以我必須更改它們的擴展名(以防止編譯時錯誤)。

我正確嗎?有沒有辦法將.mm擴展名限制在只有幾個文件?(以防止名稱衝突等)

編輯:一些更多的信息可能有所幫助,我使用LLVM 1.5作爲編譯器(我注意到編譯時錯誤的數量從GCC 4.2到LLVM 1.5有所不同,但我不確定這意味着多少,因爲我沒有看到它們全部)

回答

4

我的建議是在的#ifdefs來包裝C++位:

//MyWrapper.h 

#ifdef __cplusplus 
class ComposedClass; 
#endif 

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

// wrapped methods here... 
@end 

這是PIMPL方法的略跛版本,但更少的代碼,並有效地隱藏C++ - 從純Objective-主義C代碼。 Obvioulsy你將不得不在MyWrapper.mm包括ComposedClass的標題。

如果ComposedClass是一個模板類型,您將需要第一個塊修改到

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

而是採用了向前聲明,然後,當然,在你的Objective-C類使用模板類型實例變量聲明。

此方法是由蘋果公司的運行專家Greg Parker編寫的suggested

+0

我不認爲這是個好主意。任何包含此頭文件的非C++文件都不會「看到」受保護的成員,因此對於類和實例變量的不同偏移量將具有不同的大小。 – 2010-09-26 18:28:37

+0

@Kristopher,使用現代Objective-C運行時(這是iOS上的唯一選項),實例變量非易碎,這不是問題。 – 2010-09-26 18:29:27

+0

@Barry Wark ty Barry這似乎是對我來說最簡單的方式,但似乎我無法實現這一點,因爲我得到編譯時錯誤http://pastebin.com/tp9Zjhss好像我錯過了一些東西,我想他們可能是模板,但在你的鏈接中使用它們。 – rano 2010-09-26 19:04:16

2

我不知道我理解你的問題完全,但我認爲答案是'是'。

基本上任何需要引用包裝類的東西都是Objective-C++代碼,而不是直接的C++。

我建議你限制你的包裝類包含實現(也叫做.cpp或Objective-C++等效)文件。他們不應該使頭文件描述它們實現的類成爲Objective-C++。

Pimpl idiom這樣的技術可以幫助隔離類的用戶,而不是部分用Objective-C++實現的。

+0

+1我通過在'.mm'文件中包含了限制級聯的意見 – rano 2010-09-26 19:05:52

+0

@rano - 看起來您的問題與我描述的解決方案相反。它看起來像Objective-C/C++沒有與類定義分開的實現概念。這使工作變得更加困難,並且需要比我對Objective-C/C++的更多理解。 – Omnifarious 2010-09-26 19:35:19

+0

我現在不明白你的觀點,objective-C/C++爲接口/類的實現提供了分離 – rano 2010-09-26 20:04:54

4

任何包含C++代碼片段(無論多小)的代碼都必須使用Objective-C++進行編譯(因此必須位於.mm文件中)。如果要縮小.mm文件的數量,則必須將C++代碼的功能包裝在Objective-C類中,以便該類的公共接口(其.h文件)只包含Objective-C代碼。這意味着包裝類不能包含C++類型的公共ivar。如果你的C++庫只包含一個數據結構,這是否是一種可行的方法,我不知道。

請注意,AFAIK LLVM 1.5不包括C++支持(僅限LLVM 2.0)。 AFAIK,當您選擇LLVM 1.5時,Xcode將自動切換到所有C++/Objective-C++文件的GCC。

+0

+1爲編譯器困境啓蒙:) – rano 2010-09-26 19:07:57

1

我首選的方案是這樣的向前聲明宏:

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

FORWARD(SomeCppClass); 

@interface MyObjcWrapper : NSObject { 
    SomeCppClass *ptr; 
} 

然後MyObjcWrapper.h是安全的使用Objective-C和Objective-C++文件包括。

這是來自一篇有用的博客文章,我看到了幾年後 - 現在似乎無法找到它。