回答:
はい、もちろんApples Cライブラリとやり取りできます。ここではその方法を説明します。
基本的に、Cタイプ、CポインターなどはSwiftオブジェクトに変換されます。たとえば、int
SwiftのC はCInt
です。
CとSwiftをブリッジする方法についての小さな説明として使用できる別の質問のために、小さな例を作成しました。
main.swift
import Foundation
var output: CInt = 0
getInput(&output)
println(output)
UserInput.c
#include <stdio.h>
void getInput(int *output) {
scanf("%i", output);
}
cliinput-Bridging-Header.h
void getInput(int *output);
これが元の答えです。
コンパイラーは、Objective-Cの場合と同様に、C APIをSwiftに変換します。
import Cocoa
let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
import Darwin
for _ in 1..10 {
println(rand() % 100)
}
ドキュメントのObjective-C APIの操作をご覧ください。
CFTypeRef
)はSwiftオブジェクトに変換されます。ただし、ObjCRuntime.h関数のほとんどはSwiftにとって意味がありません。
私と同じくらいXCodeが初めてで、Leandroの回答に投稿されたスニペットを試してみたい場合に備えて:
この投稿では、clangのモジュールサポートを使用してこれを行う方法についても説明しています。
これはCommonCryptoプロジェクトでこれを行う方法の点でフレーム化されていますが、一般的にはSwift内から使用したい他のCライブラリーでも機能するはずです。
これをzlibで簡単に試してみました。新しいiOSフレームワークプロジェクトを作成し、以下を含むmodule.modulemapファイルを含むディレクトリzlibを作成しました。
module zlib [system] [extern_c] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/zlib.h"
export *
}
次に、[ターゲット]-> [ライブラリとバイナリをリンク]で、アイテムの追加を選択してlibz.tbdを追加しました。
この時点でビルドすることをお勧めします。
その後、次のコードを書くことができました。
import zlib
public class Zlib {
public class func zlibCompileFlags() -> UInt {
return zlib.zlibCompileFlags()
}
}
上記の場合を除いて、zlibライブラリ名を前に置く必要はありません。ただし、SwiftクラスfuncにC関数と同じ名前を付けましたが、修飾がないと、アプリケーションが停止するまでSwift funcが繰り返し呼び出されます。
c ++の場合、ポップアップするこのエラーがあります:
"_getInput", referenced from:
C ++ヘッダーファイルも必要です。関数にcリンケージを追加し、ブリッジヘッダーにヘッダーファイルを含めます。
スウィフト3
UserInput.h
#ifndef USERINPUT_H
#define USERINPUT_H
#ifdef __cplusplus
extern "C"{
#endif
getInput(int *output);
#ifdef __cplusplus
}
#endif
UserInput.c
#include <stdio.h>
void getInput(int *output) {
scanf("%i", output);
}
main.swift
import Foundation
var output: CInt = 0
getInput(&output)
print(output)
cliinput-Bridging-Header.h
#include "UserInput.h"
これはこれを説明するオリジナルビデオです
__OBJC
、Bridging-Headerにチェックを追加してみてください。例#ifdef __OBJC @import UIKit; #endif
ポインターを操作するときは、かなり異なるボールのように見えます。C POSIX read
システムコールを呼び出すために私がこれまでに持っているものは次のとおりです。
enum FileReadableStreamError : Error {
case failedOnRead
}
// Some help from: http://stackoverflow.com/questions/38983277/how-to-get-bytes-out-of-an-unsafemutablerawpointer
// and https://gist.github.com/kirsteins/6d6e96380db677169831
override func readBytes(size:UInt32) throws -> [UInt8]? {
guard let unsafeMutableRawPointer = malloc(Int(size)) else {
return nil
}
let numberBytesRead = read(fd, unsafeMutableRawPointer, Int(size))
if numberBytesRead < 0 {
free(unsafeMutableRawPointer)
throw FileReadableStreamError.failedOnRead
}
if numberBytesRead == 0 {
free(unsafeMutableRawPointer)
return nil
}
let unsafeBufferPointer = UnsafeBufferPointer(start: unsafeMutableRawPointer.assumingMemoryBound(to: UInt8.self), count: numberBytesRead)
let results = Array<UInt8>(unsafeBufferPointer)
free(unsafeMutableRawPointer)
return results
}