SwiftPM で C言語を含むライブラリを作る


SwiftPM で C言語を含むライブラリを作った

WorldInApple の実装

やったこと

  • 公式ドキュメントの Creating C Language Targets の通りです
  • C++ で実装された World 本体のターゲットを作成し、Swift のラッパーのターゲットから依存させました

Package.swift

-> https://github.com/fuziki/WorldInApple/blob/develop/Package.swift

import PackageDescription

let package = Package(
    name: "WorldInApple",
    platforms: [.iOS(.v11), .macOS(SupportedPlatform.MacOSVersion.v10_15)],
    products: [
        .library(
            name: "WorldInApple",
            targets: ["WorldInApple"]),
    ],
    targets: [
        // C++ で書かれた、World 本体
        .target(
            name: "WorldLib"
        ),
        // WorldLib の Swift ラッパー
        .target(
            name: "WorldInApple",
            dependencies: ["WorldLib"]),  // WorldLib に依存
    ]
)

WorldLib

WorldLib/include/World.h

-> https://github.com/fuziki/WorldInApple/blob/develop/Sources/WorldLib/include/World.h

  • WorldLib の公開されるヘッダです
  • World の必要なヘッダを公開しています
#import "../world/dio.h"
#import "../world/stonemask.h"
#import "../world/cheaptrick.h"
#import "../world/d4c.h"
#import "../world/synthesis.h"
#import "../world/harvest.h"
#import "../world/synthesisrealtime.h"
#import "../world/matlabfunctions.h"

WorldInApple

  • WorldLib の Swift ラッパーです
  • import WorldLib することで、World て定義された機能を利用できます

-> https://github.com/fuziki/WorldInApple/blob/develop/Sources/WorldInApple/WorldInAppleComponents/AperiodicityEstimator.swift

import WorldLib

public class AperiodicityEstimator: WorldInAppleComponents {
    private var d4cOption = D4COption() // World で定義された構造体が利用できる
    //〜中略〜
    public func estimatAperiodicity(x: UnsafeMutablePointer<Double>, x_length: Int32) {
        // World で定義された関数が利用できる
        D4C(x, x_length, Int32(parameters.fs), parameters.time_axis, parameters.f0, Int32(parameters.f0_length), Int32(parameters.fft_size), &d4cOption, parameters.aperiodicity)
    }
}

サンプルの実装 (Examples)

  • WorldInApple の パッケージから参照されないようにダミーの Package.swift を配置しています

-> https://github.com/fuziki/WorldInApple/blob/develop/Examples/Package.swift

import PackageDescription

let package = Package(
  name: "dummy",
  products: [],
  targets: []
)
  • WorldInApple.xcworkspace から実行可能です
  • Examples プロジェクトと、WorldInApple のパッケージが入っています

  • Examples ターゲットから WorldInApple を参照しています

  • import WorldInApple することで、作成した World の Swift のラッパーを利用可能です

-> https://github.com/fuziki/WorldInApple/blob/develop/Examples/Examples/Shared/ContentViewModel.swift

import AVFoundation
import Combine
import Foundation
import SwiftUI
import WorldInApple

class ContentViewModel: ObservableObject {

    private let world = WorldInApple(fs: 48000, frame_period: 5, x_length: 38400)
    // 〜中略〜
}

公開する & 利用する

  • GitHub に push することで、pure swift のパッケージ同様に利用することが可能でした