Risposte:
Sì, puoi ovviamente interagire con le librerie Apples C. Ecco spiegato come.
Fondamentalmente, i tipi C, i puntatori C, ecc. Vengono tradotti in oggetti Swift, ad esempio una C intin Swift è aCInt .
Ho creato un piccolo esempio, per un'altra domanda, che può essere usata come una piccola spiegazione, su come creare un ponte tra C e 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);
Ecco la risposta originale.
Il compilatore converte l'API C in Swift proprio come fa per Objective-C.
import Cocoa
let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
import Darwin
for _ in 1..10 {
println(rand() % 100)
}
Vedi Interazione con le API di Objective-C nei documenti.
CFTypeRef) vengono convertiti in oggetti Swift. Tuttavia, la maggior parte delle funzioni di ObjCRuntime.h non sono significative per Swift.
Nel caso in cui tu sia nuovo su XCode come me e desideri provare i frammenti pubblicati nella risposta di Leandro :
Questo post ha anche una buona spiegazione su come farlo usando il supporto del modulo di clang .
È strutturato in termini di come eseguire questa operazione per il progetto CommonCrypto, ma in generale dovrebbe funzionare per qualsiasi altra libreria C che si desidera utilizzare all'interno di Swift.
Ho brevemente provato a farlo per zlib. Ho creato un nuovo progetto di framework iOS e creato una directory zlib, contenente un file module.modulemap con il seguente:
module zlib [system] [extern_c] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/zlib.h"
export *
}
Quindi in Target -> Collega binario con librerie ho selezionato aggiungi elementi e aggiunto libz.tbd.
Potresti voler costruire a questo punto.
Sono stato quindi in grado di scrivere il seguente codice:
import zlib
public class Zlib {
public class func zlibCompileFlags() -> UInt {
return zlib.zlibCompileFlags()
}
}
Non è necessario mettere il nome della libreria zlib in primo piano, tranne che nel caso precedente ho chiamato la funzione Swift class come la funzione C, e senza la qualifica la funzione Swift finisce per essere chiamata ripetutamente fino a quando l'applicazione non si ferma.
Nel caso di c ++, si verifica questo errore:
"_getInput", referenced from:
È necessario anche un file di intestazione c ++. Aggiungi c-linkage alla tua funzione, quindi includi il file header nell'intestazione bridge:
Swift 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"
Ecco il video originale che spiega questo
__OBJCcontrollo al tuo Bridging-Header, ad es#ifdef __OBJC @import UIKit; #endif
Sembra essere una palla piuttosto diversa quando si tratta di puntatori. Ecco cosa ho finora per chiamare la readchiamata di sistema 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
}