我有一个C ++库(仅限.h),它包含数据结构的实现,我想在我的iPhone应用程序中使用它。
首先,我在Objective-C ++中编写了一个包装器作为一个类,通过组合,它有一个C ++类的ivar。然后我'不得不'将包装类扩展名更改为.mm
,看起来很好。但是我必须将这个包装的类文件包含在其他几个文件中,所以我也必须更改它们的扩展名(为了防止编译时错误)。
我说错了吗?有没有办法将.mm扩展名“限制”为几个文件?(以防止名称冲突等)
编辑:可能有帮助的更多信息,我使用LLVM 1.5作为编译器(我注意到编译时错误的数量从GCC 4.2到LLVM 1.5不等但我不确定它意味着什么,因为我没看过他们所有人)答案 0 :(得分: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代码的主义。很遗憾,您必须在ComposedClass
中添加MyWrapper.mm
标题。
如果ComposedClass
是模板化类型,则需要将第一个块修改为
#ifdef __cplusplus
#include "ComposedClass.h"
#endif
而不是使用前向声明,然后,当然,在Objective-C类的实例变量声明中使用模板化类型。
此方法由Apple的运行时专家Greg Parker suggested提供。
答案 1 :(得分:4)
任何包含C ++代码段的代码(无论多小)都必须使用Objective-C ++进行编译(因此必须在.mm文件中)。如果要缩小.mm文件的数量,则必须在Objective-C类中包含C ++代码的功能,以便此类的公共接口(其.h文件)仅包含Objective-C代码。这意味着包装类不能包含C ++类型的公共ivar。如果你的C ++ lib只包含数据结构,这是否是一种可行的方法,我不知道。
请注意,AFAIK LLVM 1.5尚不包含C ++支持(仅限LLVM 2.0)。 AFAIK,当您选择LLVM 1.5时,Xcode将自动切换到GCC以获取所有C ++ / Objective-C ++文件。
答案 2 :(得分:2)
我不确定我完全理解你的问题,但我认为答案是'是'。
基本上任何需要引用包装类的东西都是Objective-C ++代码,而不是直接的C ++。
我建议您将包装类包含在实现(aka .cpp
或Objective-C ++等效文件)中。它们不应该导致描述它们实现的类的头文件成为Objective-C ++。
像Pimpl idiom这样的技术可以帮助您将类的用户与其部分用Objective-C ++实现的事实隔离开来。
答案 3 :(得分: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 ++文件中。
这是我几年前看到的一篇有用的博客文章 - 现在似乎无法找到它。