Відповіді:
Так, ви, звичайно, можете взаємодіяти з бібліотеками Apples C. Ось пояснено, як.
В основному типи C, покажчики C тощо переводяться на об'єкти Swift, наприклад, C int
у Swift є a CInt
.
Я буду буду крихітний приклад для іншого питання, яке можна використати як невелике пояснення, як перейти між C і 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);
Ось оригінальна відповідь.
Компілятор перетворює API C у Swift так само, як це робиться для Objective-C.
import Cocoa
let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
import Darwin
for _ in 1..10 {
println(rand() % 100)
}
Див. Розділ Взаємодія з API-кодом Objective-C у документах.
CFTypeRef
) у стилі CoreFoundation перетворюються на об'єкти Swift. Більшість функцій ObjCRuntime.h, однак, не мають сенсу для Swift.
На всякий випадок, якщо ви настільки новачок у XCode, як я, і хочете спробувати фрагменти, розміщені у відповіді Леандро :
Цей пост також має гарне пояснення щодо того, як це зробити, використовуючи підтримку модуля clang .
Це обрамлено з точки зору того, як це зробити для проекту CommonCrypto, але в цілому він повинен працювати для будь-якої іншої бібліотеки C, яку ви хочете використовувати з Swift.
Я коротко експериментував, роблячи це для zlib. Я створив новий рамковий проект iOS та створив каталог zlib, що містить файл module.modulemap із наступним:
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 таким же, як і функцію C, і без кваліфікації функція Swift закінчується повторним викликом, поки програма не зупиниться.
У випадку 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);
}
головна
import Foundation
var output: CInt = 0
getInput(&output)
print(output)
cliinput-Bridging-Header.h
#include "UserInput.h"
Ось оригінальне відео, що пояснює це
__OBJC
чек до #ifdef __OBJC @import UIKit; #endif
Це, мабуть, зовсім інший кульковий віск при роботі з покажчиками. Ось що я досі мав для виклику read
системного виклику C POSIX :
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
}