LoginSignup
0
0

More than 3 years have passed since last update.

Swiftの構造体はC++に渡せるよって話

Last updated at Posted at 2020-05-27

! C++とSwift間で構造体を渡すことは保証されておらず、メモリレイアウトが異なる場合があるそうです。

この記事は参考程度に

背景

Swiftは比較的高速な言語ですが、やっぱり速度面でC++を使いたくなることはあります。

しかし、Swiftが直接サポートしているのはCからのブリッジのみです。なので、
C++の構造体をObjCでラップして... 
なんて形で渡すことが多いです。

でもこれだとかなりオーバヘッドが大きくて(特にObjCの動的ディスパッチあたりが)、結局C++を使った意味は...?となることが多いです。

なので、実はSwiftの構造体くらいならC++に直接渡せるよって話です。

実験

Swiftでこんな構造体を作ります。

struct Point {
    var x: Double
    var y: Double
}
struct Size {
    var width: Double
    var height: Double
}
struct Rect {
    var origin: Point
    var size: Size
}

それをポインタにして、cppcallに投げます。

var frame = Rect(origin: Point(x: 100, y: 200), size: Size(width: 300, height: 400))

withUnsafeMutablePointer(to: &frame) {ptr in
    cppcall(UnsafeMutableRawPointer(ptr))
}

次にC++側です。

Swiftで定義した構造体と同じ構造を持つ構造体をC++側で定義します。

struct Point {
    double x;
    double y;
};

struct Size {
    double width;
    double height;
};

struct Rect {
    Point origin;
    Size size;
};

void cppcall(void *swiftStruct) {

    auto casted = (struct Rect*)(swiftStruct);

    std::cout << casted->origin.x << std::endl;
    std::cout << casted->size.height << std::endl;
}

Headerで以下のようにextern "C"します。受け取るのは void*型です。

extern "C" {

void cppcall(void* swiftStruct);

}

これで、実行するとそのままC++にSwiftでインスタンス化した構造体がC++で使えます。

解説のようなもの

これがうまく行くのはSwiftとC++でメモリ上の構造体の扱いが同じだからです。どちらもメンバーを最初から順番にメモリに並べているだけです。(SwiftはOptionalな構造体ではちょっと扱いが変わりますが...)

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0