轉自 http://www.cnblogs.com/biosli/archive/2011/04/30/Mixing_ObjectiveC_and_Cplusplus_in_iPhone_Development.html
先說題外話,文章標題其實起的不好,在iOS的開發中,Apple建立的庫基本都是用Objective-C寫的,所以在這裡的C++指的其實是Objective-C++。
首先,最最最要緊的事情,不是代碼而是編譯器選項,在做混合編譯之前一定要把編譯器的Compile Sources As選項改為Objective C++。
預設的選項是According to file type,用這個的話,你後面每個不在交叉行列裡的類都OK,一旦兩種語言在一個檔案中相互調用,就會報錯,而且報的錯怪的很,比如:找不到new,找不到delete,等等。
既然是調用嘛,肯定要有來有往,先說說,在C++中如何調用Objective-C:(參考這個,我略做修改)
1. 封裝Objective-C的對象函數變為C的函數介面
2. 寫一個對應的C++類調用
說起來簡單,看看例子就知道什麼情況了。
//MyObject-C-Interface.h
#ifndef __MYOBJECT_C_INTERFACE_H__
#define __MYOBJECT_C_INTERFACE_H__ 1
int MyObjectDoSomethingWith (void *myObjectInstance, void *parameter);
#endif
//MyObject.h
#import "MyObject-C-Interface.h"
@interface MyObject : NSObject
{
int someVar;
}
- (int) doSomethingWith:(void *) aParameter;
@end
//MyObject.m
#import "MyObject.h"
int MyObjectDoSomethingWith (void *self, void *aParameter)
{
return [(id) self doSomethingWith:aParameter];
}
@implementation MyObject
- (int) doSomethingWith:(void *) aParameter
{
// ... some code
return 1;
}
@end
//MyCPPClass.h
#ifndef __MYCPPCLASS_H__
#define __MYCPPCLASS_H__
class MyCppClass
{
public:
int MyCPPClass::someMethod (void *objectiveCObject, void *aParameter);
}
#endif
//MyCPPClass.cpp
#include "MyCPPClass.h"
#include "MyObject-C-Interface.h"
int MyCPPClass::someMethod (void *objectiveCObject, void *aParameter)
{
return MyObjectDoSomethingWith (objectiveCObject, aParameter);
}
如上面所示,先搞個弱類型的C函數介面,然後在Objective C的類中實現該介面。最後,在C++的類中調用弱類型,和弱介面。
在工程主體架構是用Objective-C寫成的前提下,上面的這種調用並不實用,完全是技術可能性的研究。說白了,就是騙騙編譯器玩,同時也失去了C++優雅的強型別特性。
下面這個才是真金白銀有用的,在Objective-C代碼下調用C++類代碼:
1. 建立一個C++類
2. 寫一個Adaptor的Objective-C類
3. 在其他Objective-C的邏輯中調用Adaptor類。
還是代碼:)
//
// CPlusPlusClass.h
// MixCompileTest
//
// Created by biosli on 11-4-30.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#ifndef __CPLUSPLUS_CLASS_H__
#define __CPLUSPLUS_CLASS_H__
class CPlusPlusClass {
public:
CPlusPlusClass();
virtual ~CPlusPlusClass();
void func();
void setInt (int i) {
m_i = i;
}
private:
int m_i;
};
#endif
//
// CPlusPlusClass.mm
// MixCompileTest
//
// Created by biosli on 11-4-30.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#include <stdio.h>
#include "CPlusPlusClass.h"
CPlusPlusClass::CPlusPlusClass() : m_i(0)
{
printf("CPlusPlusClass::CPlusPlusClass()\n");
func();
}
CPlusPlusClass::~CPlusPlusClass()
{
printf("CPlusPlusClass::~CPlusPlusClass()\n");
}
void CPlusPlusClass::func() {
printf("CPlusPlusClass func print: %d\n", m_i);
}
//
// ObjectiveCAdaptor.h
// MixCompileTest
//
// Created by biosli on 11-4-30.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
class CPlusPlusClass; //這個聲明得小心,千萬不要寫成@class,兄弟我搞了半宿才找到這個錯誤。呵呵,見笑,見笑。
@interface ObjectiveCAdaptor : NSObject {
@private
CPlusPlusClass *testObj;
}
- (void) objectiveFunc;
@end
//
// ObjectiveCAdaptor.m
// MixCompileTest
//
// Created by biosli on 11-4-30.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "ObjectiveCAdaptor.h"
#include "CPlusPlusClass.h"
@implementation ObjectiveCAdaptor
- (id) init {
if (self = [super init]) {
testObj = new CPlusPlusClass();
}
return self;
}
- (void) dealloc {
if (testObj != NULL) {
delete testObj;
testObj = NULL;
}
[super dealloc];
}
- (void) objectiveFunc
{
testObj->setInt(5);
testObj->func();
@end
//調用樣本:
- (void) callObjectiveCAdaptorMethod
{
ObjectiveCAdaptor *testObjectiveCObj = [[ObjectiveCAdaptor alloc] init];
[testObjectiveCObj objectiveFunc];
[testObjectiveCObj release];
}
上面這個例子示範了建立C++類,建立Objective-C的Adaptor類,和最後調用的全過程。
在編寫混合編譯代碼時一定要記住一個原則,Objective-C++這個東東包含了Objective-C和C++的所有關鍵字和符號,所以在編寫交叉編譯代碼時,千萬不要用混本來就很像的關鍵字和符號。
參考資料:
具體的代碼限制:請參考《Objective-C和C++混編的要點》
混合編譯好處多,這篇文章敘述的相當到位《Strategies for Using C++ in Objective-C Projects》