Posted at
NIJIBOXDay 9

swiftでc++の資産を使おう

More than 1 year has passed since last update.

あまりないかもしれませんが、

SwiftからC++のライブラリを呼び出す参考になればと、

C++を呼び出す方法について書いています。

cocos2d-xの資産なんかを転用したいときに使えるかも。


SwiftからC++を呼び出す方法

実はSwiftから直接C++を呼び出すことはできません。

そこで、objective-Cのラッパー関数を用いてそこからC++を呼び出すことになります。

C++のCppClassのラッパーがobjective-CのObjcClassであったとすると、


test.swift

import UIKit

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

// ブリッジングヘッダでimportすれば、自動的にimportされてるみたい
let obj = ObjcClass()
obj.add(10)
obj.add(20)
obj.add(30)
let arr = obj.getList()
print(arr)
}
}


といった記述で、CppClassのSTLのvectorに保存するadd関数を呼び出すことにします。

getListは確認用にラッパー関数上で実装されたvector内部をNSArray化する関数です。

ターゲットになるCppClassはこんな感じです。あんまり意味のない内容ですが。。。


CppClass.h

#include <vector>


class CppClass {
public:
std::vector vct;
void add(int data) { vct.push_back(data); };
}

まず、swiftのプロジェクト上でラッパー関数になるObjective-cのファイルを作ります。

IDE上で.mmファイルを生成すると、<ProjectName>-Bridinging-Header.hを作るかどうかダイアログが開くので「はい」を選択します。

この中身は空なので、これから作る.mmファイルのヘッダーファイルをimportするように記述します。


ProjectName-Bridging-Header.h

//

// Use this file to import your target's public headers that you would like to expose to Swift.
//

#import "ObjcClass.h"


ヘッダはこんな感じで。


ObjcClass.h

#import <Foundation/Foundation.h>


@interface ObjcClass : NSObject
{
void* _cppObj; // C++クラスのインスタンスを参照するポインタ
}

-(void)add:(int)data;
-(NSArray*)getList;

@end


次にラッパー関数.mmファイルを作ります。


ObjcClass.mm

#import "ObjcClass.h"

#include "CppClass.h"

@implementation ObjcClass

-(id)init {
self = [super init];

if (self) {
_cppObj = new CppClass();
}

return self;
}

-(int)add:(int)data {
CppClass& obj = *static_cast<CppClass*>(_cppObj);
obj.add(data);
}

-(NSArray*)getList {
CppClass& obj = *static_cast<CppClass*>(_cppObj);
NSMutableArray *tmpArray = [NSMutableArray arrayWithCapacity:(obj.vct).size()];
for (int i=0;i<(obj.vct).size();i++) {
[tmpArray addObject:[NSNumber numberSithInt:obj.vct[i]]];
}
return [NSArray arrayWithArray:tmpArray];
}

@end


getListは動作確認のために作った関数なので、add関数だけに注目すればそれほど難しいものではないことは判るかと。また、C++からの戻り値を変換して渡す必要がある場合は参考になるかと思われるので、わざわざ書いてみました。

これで、C++の資産をswiftからも利用できるようになります。

ちょっとラッパー関数を作るのが面倒ですが、まぁ良しとしましょう。