iOSiOS学习游戏开发

oc与c++混编,抛弃.mm文件

2016-06-12  本文已影响993人  owlwisp

写这片文章的起因是,有些朋友不想使用oc++的全部.mm文件的写法,固才有这种混编的转化的方法前期准备:

  1. 首先建立一个新工程,编译,运行,ok 没问题,进入第2步
  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 语言的混编

  1. 我们建立一个 "COCFile_State_1.cpp" 的中转类,将尾缀修改为".mm ".并将头文件放到 "HelloWorldScene.m"中,编译测试。没问题,下一步。
  2. 在 "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>
  1. 这样就可以在"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也是类似的情况。

思考:

  1. 其实我们可以仔细看一眼state_2的步骤2,3和state_1的步骤2,3有什么区别?
  2. 有没有发现其实抛去方法来看,他们都只是一个遵守一个规则的?

原则:c++写在 .cpp中, oc 写在.m 中,oc与c++混编那么就需要.mm。

那么我在c++中调用c++的代码总没问题把,这样只需要.cpp就可以了. oc的同理
所以,你只需要想尽一切办法 将oc的方法 转化成一个个c/c++接口来给c++调用就可以了。
好吧就写道这里了。估计现在你应该很清楚怎样去混编c++与oc 了

另:可能上面步骤比较罗嗦,但我还是比较喜欢这种小步进步,步步为营的方式,这样不会出现非常严重的问题,也不会突然束手无策。

上一篇下一篇

猜你喜欢

热点阅读