我正在尝试在Objective-C中创建一个包装器,所以我不必在库类之外编写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 Target Properties的事实:?
Other Link Flags : -lstdc++ -lz
或许我需要在这里添加新标志?
提前致谢
答案 0 :(得分:6)
您的问题是.m
文件被编译为C而不是C ++。因此,当编译器在编译.m
文件时,即使在头文件中遇到任何C ++,它也会被禁止。
毫无疑问,你必须在头文件中加入一些C ++,因为你的Objective C对象包装了一个C ++对象,但是有很多方法可以解决这个问题。一种方法是使用指向C ++对象的指针,并使用为C ++(和Objective-C ++)定义但不适用于C(或Objective-C)的方便的预处理器定义__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
由于您永远不会取消引用.mm
文件之外的cppObject成员,因此您从不提供结构的完整定义并不重要。
new
和delete
分别指向-init
和-dealloc
。您将在LLAHProcessorWrapper.mm
中包含完整的C ++类声明。
答案 1 :(得分:4)
您需要做的就是像创建一样.mm
,编译器应该处理所有事情。
需要注意的是,在.h
文件中有任何与C ++相关的内容是不安全的,因为它们可以/将由其他仅有Objective-C的文件导入,然后一切都会崩溃。这里的主要问题是你不能直接将C ++类型定义为Objective-C包装类的实例变量,除非每个.m
文件都被重命名为Objective-C ++ .mm
文件。
解决方案是在头文件中将实例变量定义为void*
,并使用实现文件中的类型转换来访问它们。最简单的解决方案是使用为您进行类型转换的私有属性来访问实例变量。
示例代码假设Foo
是Foo.h
中定义的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
答案 2 :(得分:0)
在您要引用.h
的任何标头(LLAHProcessorWrapper
)文件中,使用正向类定义而不是导入,如下所示:
@class LLAHProcessorWrapper;
@interface SomeView : UIView {
LLAHProcessorWrapper *wrapper;
}
并确保相应的实施文件包含#include LLAHProcessorWrapper.h
或#import LLAHProcessorWrapper.h
。
如果#include
或整个包含树中的任何其他内容,则#import
或.mm
标题必须以LLAHProcessorWrapper.h
为后缀的任何实施文件< / em>有任何C ++语法。这样,有一个.mm
文件倾向于表示代码库的大部分必须将其文件重命名为.mm
。