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 int
in 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
__OBJC
controllo 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 read
chiamata 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
}