読者です 読者をやめる 読者になる 読者になる

Pebble's Diary

プログラマーの作業メモ

Cの構造体を引数でswiftに渡す

swift

構造体も構造体ポインタもどちらも渡せるが、構造体ポインタのときはmemoryとたくさん書くことになる。ソース可読性を優先すると構造体の方がよさそう。速度については構造体ポインタの方が若干速いようだ。

swift1.2 Optimization Level : Fasttest [-O]
1,000,000回の呼び出し
構造体版 6,898 us
構造体ポインタ版 5,371 us

main.m

#import <Foundation/Foundation.h>
#import "caller.h"
#import "sample-swift.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        invoke();
    }
    return 0;
}

caller.h

#import <Foundation/Foundation.h>

typedef struct Params_t {
    int32_t v;
    int32_t* p;
    int32_t** pp;
} Params;

@protocol Jedi
- (void)useTheForceWithParams:(Params)params;
- (void)useTheForceWithParamsPointer:(Params*)p_params;
@end

void invoke(void);

caller.m

#import "caller.h"
#import "sample-swift.h"

void invoke(void){
    {
        Callee* callee = [[Callee alloc] init];
        Params params;
        params.v = 1;
        
        int32_t a = 2;
        params.p = &a;
        
        int32_t x1 = 3;
        int32_t x2 = 4;
        int32_t* y[2] = {&x1, &x2};
        params.pp = y;
        [callee useTheForceWithParams:params];
        
        assert( params.v == 1 );
        assert( a == 11 );
        assert( x1 == 12 );
        assert( x2 == 13 );
    }
    {
        Callee* callee = [[Callee alloc] init];
        Params params;
        params.v = 1;
        
        int32_t a = 2;
        params.p = &a;
        
        int32_t x1 = 3;
        int32_t x2 = 4;
        int32_t* y[2] = {&x1, &x2};
        params.pp = y;
        [callee useTheForceWithParamsPointer:&params];
        assert(params.v == 14);
        assert(a == 15);
        assert(x1 == 16);
        assert(x2 == 17);
    }
}

callee.swift

import Foundation

@objc class Callee : NSObject, Jedi {
    override init(){
        super.init()
    }
    func useTheForceWithParams(params:Params){
        assert(params.v == 1)
        assert(params.p[0] == 2)
        params.p[0] = 11 
        var qq:UnsafeMutablePointer<UnsafeMutablePointer<Int32>> = params.pp
        assert( qq[0][0] == 3 )
        assert( qq[1][0] == 4 )
        qq[0][0] = 12
        qq[1][0] = 13
    }
    func useTheForceWithParamsPointer(p_params:UnsafeMutablePointer<Params>){
        assert(p_params.memory.v == 1)
        assert(p_params.memory.p[0] == 2)
        p_params.memory.v = 14 
        p_params.memory.p[0] = 15
        var qq:UnsafeMutablePointer<UnsafeMutablePointer<Int32>> = p_params.memory.pp
        assert(qq[0][0] == 3)
        assert(qq[1][0] == 4)
        qq[0][0] = 16
        qq[1][0] = 17
    }
}

sample-Bridging-Header.h

#import "caller.h"