답변:
예, 물론 Apples C 라이브러리와 상호 작용할 수 있습니다. 방법은 다음과 같습니다 .
기본적으로 C 유형, C 포인터 등은 Swift 객체로 변환됩니다. 예를 들어 int
Swift 의 C 는 a 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()
}
}
당신은하지 않습니다 가 C 함수와 같은 FUNC 스위프트 클래스라는 이름의 위의 경우에 I를 제외하고, 앞에있는 ZLIB 라이브러리 이름을 넣어, 및 자격없이 스위프트의 FUNC의 끝이 응용 프로그램은 정지 할 때까지 반복적으로 호출된다.
c ++의 경우 다음과 같은 오류가 발생합니다.
"_getInput", referenced from:
C ++ 헤더 파일도 필요합니다. 함수에 c-linkage 를 추가 한 다음 브리지 헤더에 헤더 파일을 포함하십시오.
스위프트 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
브리징 헤더에 체크 표시 를 추가 하십시오.#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
}