Blog スタッフブログ

C++ Swift システム開発

[Swift]Xcode15/Swift5.9でSwiftからC++のコードを呼び出す

こんにちは、株式会社MIXシステム開発担当のBloomです。

早速本題のSwift5.9からC++のコードを直接呼び出す方法について、知見を共有させていただきたいと思います。

XcodeでC++ interoperabilityの設定を行う

Xcode15から利用できるようになったC++ interoperabilityの機能を利用してコード呼び出しの準備をしましょう。

まずは[C++ and Objective-C Interoperability]の項目を変更し、[C++ / Objective-C++]へ設定しましょう。

次にcppファイルを追加しましょう。追加時にBridging-Headerを追加するか否かの確認があるため同時に追加してしまいましょう。

もし追加し忘れた際は手動で追加後、[Objective-C Bridging Header]からパスを指定してあげましょう。

ここからはそれぞれのサンプルコードを掲載します。

#ifndef App_Bridging_Header_h
#define App_Bridging_Header_h

#include "CppClass.hpp"

#endif /* App_Bridging_Header_h */
#ifndef CppClass_hpp
#define CppClass_hpp

#include <stdio.h>
#include <vector>
// [Build Setting] -> [Generated Header Name]で指定されている名称のヘッダファイルを読み込みましょう
#include "sandbox-Swift.h"

class CppClass {
public:
    void helloworld(void);
    void passByValue(int value);
    void passByPointer(int *value);
    void passByReference(int &value);
    std::vector<int> toArray(int value1, int value2);
    void printString(std::string string);
};

#endif /* CppClass_hpp */
#include "CppClass.hpp"
#include "iostream"

void CppClass::helloworld(void) {
    std::cout << "Hello, World!" << std::endl;
}
void CppClass::passByValue(int value) {
    value += 1;
}
void CppClass::passByPointer(int *value) {
    *value += 1;
}
void CppClass::passByReference(int &value) {
    value += 1;
}
std::vector<int> CppClass::toArray(int value1, int value2) {
    auto retval = std::vector<int>();
    retval.push_back(value1);
    retval.push_back(value2);
    return retval;
}
void CppClass::printString(std::string string) {
    std::cout << string << std::endl;
}

ではいよいよSwiftから実行してみましょう。今回はシンプルにViewControllerから呼び出してみます。

    override func viewDidLoad() {
        super.viewDidLoad()
        var cppClass = CppClass()
        cppClass.helloworld()
        var number: Int32 = 1
        cppClass.passByValue(number)
        print(number)
        cppClass.passByPointer(&number)
        print(number)
        cppClass.passByReference(&number)
        print(number)
        let array = cppClass.toArray(1, 2)
        array.forEach { value in
            print("array elem:\(value)")
        }
        let hello: std.string = "Hello, World from Swift"
        cppClass.printString(hello)
    }

実行結果

Hello, World!
1
2
3
array elem:1
array elem:2
Hello, World from Swift

値渡し、ポインタ渡し、参照渡しもC++と同じ書式で正常に動作しています。std::vectorもSwiftからArrayのように利用できるため、値の受け渡しでつまづくことはないでしょう。良かったですね。

参考文献

[Swift] Swift 5.9 と C++ の互換性 – Qiita.com

Mixing Swift and C++ – swift.org