写这片文章的起因是,有些朋友不想使用oc++的全部.mm文件的写法,固才有这种混编的转化的方法前期准备:
- 首先建立一个新工程,编译,运行,ok 没问题,进入第2步
- 我建立了一个 "COCFile.m" 的文件,用来储存oc语言的代码,代码如下:
"COCFile.h"
<pre> #import <Foundation/Foundation.h>
@interface COCFile : NSObject{
NSString * name_;
NSNumber * count_;
}
@property (nonatomic, readwrite,copy) NSString * name_;
@property (nonatomic, readwrite,retain) NSNumber * count_;
@end</pre>
"COCFile.m"
<pre> #import "COCFile.h"
@implementation COCFile
@synthesize name_;
@synthesize count_;
-(id) init{
if(self = [super init]) {
name_ = @"text";
count_ = [NSNumber numberWithInt:3];
}
return self;
}
@end</pre>
编译,测试没问题,我们进入下一步
state_1: 头文件内不包含oc 语言的混编
- 我们建立一个 "COCFile_State_1.cpp" 的中转类,将尾缀修改为".mm ".并将头文件放到 "HelloWorldScene.m"中,编译测试。没问题,下一步。
- 在 "COCFile_State_1”创建一个c++的类,你可以选择用普通或者是单例都没问题.那么我们需要在这个类中调用 "COCFile" 的oc的代码,代码如下
"COCFile_State_1.h"
<pre> #include <iostream>
#include "CSingleton.h"
class CState_1 : public Singleton
{
public:
const char * getName();
int getCount();
const char * getMode();
};</pre>
"COCFile_State_1.mm"
<pre> #include "COCFile_State_1.h"
#import "COCFile.h"
const char * CState_1::getName(){
COCFile * file = [[[COCFile alloc]init]autorelease];
return [file.name_ UTF8String];
}
int CState_1::getCount(){
COCFile * file = [[[COCFile alloc]init]autorelease];
return [file.count_ intValue];
}
const char * CState_1::getMode(){
return [[UIDevice currentDevice].model UTF8String];
}</pre>
-
这样就可以在"HelloWorldScene"中调用这2个方法来获取原来在oc中的数据了.代码如下:
<pre> const char * name = CState_1::getInstance()->getName();
int count = CState_1::getInstance()->getCount();
const char * mode = CState_1::getInstance()->getMode();
CCLOG("name = %s",name);
CCLOG("count = %d",count);
CCLOG("mode = %s",mode);输出如下:
Cocos2d: name = text
Cocos2d: count = 3
Cocos2d: mode = iPhone Simulator</pre>
备注:这里举的例子可能不够恰当(主要是跟state2做对比),因为这种混编的情况比较实用于oc是单例类的情况。例如系统设备的 "UIDevice" 等比较合适.
state_2:头文件也需要被包含的情况,其实这就是一个转化,只需要在多包含一层就可以了,然后转化成state_1 来解决
1.我们建立一个 "COCFileState_2_Mid.mm" 的中间类,用来封装oc的代码, 代码很简单如下:
"COCFileState_2_Mid.h"
<pre> #include "CSingleton.h"
import "COCFile.h"
class CState_2_Mid :public Singleton{
private:
COCFile * m_ocFile;
~CState_2_Mid();
public:
CState_2_Mid();
COCFile getFile();
};</pre>
"COCFileState_2_Mid.mm"
<pre> CState_2_Mid::~CState_2_Mid(){
[m_ocFile release];
m_ocFile = NULL;
}
CState_2_Mid::CState_2_Mid(){
m_ocFile = [[COCFile alloc]init];
}
COCFile * CState_2_Mid::getFile(){
return m_ocFile;
}</pre>
2.下面的方法估计你看了会感觉很熟悉,是的 下面就是重复state_1那就直接上代码嘛
"CState_2.h"
<pre> #include < iostream >
include "CSingleton.h"
class CState_2:public Singleton{
public:
const char * getName();
int getCount();
};</pre>
"CState_2.mm"
<pre> #include "COCFileState_2.h"
import "COCFileState_2_Mid.h"
const char * CState_2::getName(){
COCFile * file = CState_2_Mid::getInstance()->getFile();
return [file.name_ UTF8String];
}
int CState_2::getCount(){
COCFile * file = CState_2_Mid::getInstance()->getFile();
return [file.count_ intValue];
}</pre>
3.这样就可以在HelloWorldScene中调用这2个方法来获取原来在oc中的数据了。代码如下:
<pre> const char * name_1 = CState_2::getInstance()->getName();
int count_1 = CState_2::getInstance()->getCount();
CCLOG("name_1 = %s",name_1);
CCLOG("count_1 = %d",count_1);
输出如下:
Cocos2d: name_1 = text
Cocos2d: count_1 = 3</pre>
OC转c++就是这两种情况。C++转oc也是类似的情况。
思考:
- 其实我们可以仔细看一眼state_2的步骤2,3和state_1的步骤2,3有什么区别?
- 有没有发现其实抛去方法来看,他们都只是一个遵守一个规则的?
原则:c++写在 .cpp中, oc 写在.m 中,oc与c++混编那么就需要.mm。
那么我在c++中调用c++的代码总没问题把,这样只需要.cpp就可以了. oc的同理
所以,你只需要想尽一切办法 将oc的方法 转化成一个个c/c++接口来给c++调用就可以了。
好吧就写道这里了。估计现在你应该很清楚怎样去混编c++与oc 了
另:可能上面步骤比较罗嗦,但我还是比较喜欢这种小步进步,步步为营的方式,这样不会出现非常严重的问题,也不会突然束手无策。
网友评论