Swift から C の関数を呼び出す方法を Swift-NIO のコードを読みながら試した。
プロジェクトの構造は普通の2モジュールあるプロジェクト
. ├── Package.swift ├── Sources │ ├── CExp │ │ ├── include │ │ │ └── c_exp.h │ │ └── shim.c │ └── SwiftClangCompat │ └── main.swift └── Tests ├── LinuxMain.swift └── SwiftClangCompatTests ├── SwiftClangCompatTests.swift └── XCTestManifests.swift
CExp
は C 言語の関数を呼び出すモジュールで、次のような関数を定義している
c_exp.h
#ifndef C_EXP_H #define C_EXP_H #include <stdio.h> void POSIX_print(char *string); #endif
実装はただ単に printf
を呼び出すだけ
shim.c
#include <c_exp.h> #include <stdio.h> void POSIX_print(char *string) { printf("%s\n", string); }
このモジュールを swift のモジュールが参照できるように、 Package.swift
を調整する。
// swift-tools-version:4.2 import PackageDescription let package = Package( name: "SwiftClangCompat", dependencies: [], targets: [ .target(name: "CExp", dependencies: []), .target(name: "SwiftClangCompat", dependencies: ["CExp"]), .testTarget(name: "SwiftClangCompatTests", dependencies: ["SwiftClangCompat"]), ] )
そのうえで、Swift 側で C のモジュールを import して呼び出す。
import Foundation import CExp let string = "(☝՞ਊ ՞)☝ウェーイwww " string.withCString { (strPtr: UnsafePointer<Int8>) -> Void in POSIX_print(UnsafeMutablePointer(mutating: strPtr)) }
呼び出し結果
$ swift run SwiftClangCompat (☝՞ਊ ՞)☝ウェーイwww