-----错误产生:
最近在给2dx-lua quick3.3项目接iOS广告SDK时,修改了Build Settings->Linking中的Other Linker Flags为-ObjC
并且按广告SDK文档中说的在AppDelegate.h中加入 #import "CheetahMobileAds.h"
然后运行时就会出现:
nsobjcruntime.h中出现
Expected unqualified-id
Unknown type name 'NSString'
Unknown type name 'NSString'
Unknown type name 'NSString'
Unknown type name 'NSString'
Unknown type name 'Protocol'
..
等一堆红色错误,一同出错的有三个文件:NSObjCRuntime.h NSObject.h NSZone.h
-----原因:
c++/oc混编造成。在 include的头文件中包含了”#import xxxxx”这样的代码。
-----解决方法:
将带有混编的文件的后缀名.cpp改为.mm。
1.将#import "CheetahMobileAds.h"代码放到AppDelegate.cpp中。
2.将AppDelegate.cpp改为AppDelegate.mm。
-----说明:
原文链接:http://blog.csdn.net/xuchaovip/article/details/22046115
用C++/OC混编的时候,如果不是很熟练,经常会碰到类似如下的错误:
- Parse Issue Expected unqualified-id
- Semantic Issue Unknown type name ‘NSString’; did you mean ‘CCString’?
而且这些错误通常是来自OC提供的库文件,比如说NSObjcRuntime.h,这就让人很头大,尤其是像我这样刚学OC的人。
问题解决起来很简单,首先检查xcode设置,把编译器的Compile Sources As选项改为Objective C++;其次仔细检查.cpp文件,看有没有include的头文件中包含了”#import xxxxx”这样的代码。如果有的话,则存在C++/OC的混编,需要将.cpp后缀修改为.mm后缀,这是因为Xcode需要源文件以”.mm”为扩展名,这样才能启动编译器的Objective-C++扩展,否则会把.cpp文件直接按c style来编译,遇到OC的东西,自然就无法解析了。
这里贴一个典型的例子,有下面两个类A、B(类的功能可能有些牵强,但是不影响理解),一个是C++ style,一个是OC style。这种情况下,编译器就会报类似如上的错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// A.h
#include <iostream>
using
namespace
std;
class
A
{
public
:
void
printB();
};
// A.cpp
#include "A.h"
#include "B.h"
void
A::printB
{
B* b = [[B alloc] init];
[b display];
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// B.h
#import <Foundation/Foundation.h>
@interface
B :
NSObject
{
float
_b;
}
- (
void
) display;
@end
// B.m
#import "B.h"
@implementation
B
- (
void
) display
{
NSLog
(
@"_b = %f"
, _b);
}
@end
|
-----补充:
关于Xcode上的Other linker flags
Targets选项下有Other linker flags的设置,用来填写XCode的链接器参数,如:-ObjC -all_load -force_load等。
还记得我们在学习C程序的时候,从C代码到可执行文件经历的步骤是:
源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件
在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。
如果要详细研究链接器做了什么,请看:http://www.dutor.net/index.php/2012/02/what-linkers-do/
那么,Other linker flags设置的值实际上就是ld命令执行时后面所加的参数。
下面逐个介绍3个常用参数:
-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中
-all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。
-force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载