Respostas:
Sim, é claro que você pode interagir com as bibliotecas da Apples C. Aqui está explicado como.
Basicamente, os tipos C, ponteiros C, etc. são convertidos em objetos Swift, por exemplo, um C int
no Swift é a CInt
.
Criei um pequeno exemplo, para outra pergunta, que pode ser usada como uma pequena explicação, sobre como fazer a ponte entre 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);
Aqui está a resposta original.
O compilador converte a API C em Swift, assim como faz para o Objective-C.
import Cocoa
let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
import Darwin
for _ in 1..10 {
println(rand() % 100)
}
Consulte Interagindo com APIs do Objective-C nos documentos.
CFTypeRef
) no estilo CoreFoundation são convertidos em objetos Swift. A maioria das funções ObjCRuntime.h não são significativas para o Swift.
Caso você seja tão novo no XCode quanto eu e queira experimentar os trechos publicados na resposta de Leandro :
Este post também tem uma boa explicação sobre como fazer isso usando o suporte ao módulo do clang .
Ele está estruturado em termos de como fazer isso no projeto CommonCrypto, mas, em geral, deve funcionar para qualquer outra biblioteca C que você deseja usar no Swift.
Eu experimentei brevemente fazer isso para zlib. Criei um novo projeto de estrutura do iOS e criei um diretório zlib, contendo um arquivo module.modulemap com o seguinte:
module zlib [system] [extern_c] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/zlib.h"
export *
}
Em Targets -> Link Binary With Libraries, selecionei add items e adicionei libz.tbd.
Você pode querer construir neste momento.
Pude escrever o seguinte código:
import zlib
public class Zlib {
public class func zlibCompileFlags() -> UInt {
return zlib.zlibCompileFlags()
}
}
Você não precisa colocar o nome da biblioteca zlib na frente, exceto no caso acima, que chamei a classe Swift func da mesma forma que a função C, e sem a qualificação, a função Swift acaba sendo chamada repetidamente até que o aplicativo pare.
No caso de c ++, existe este erro que aparece:
"_getInput", referenced from:
Você também precisa de um arquivo de cabeçalho c ++. Adicione c-linkage à sua função e inclua o arquivo de cabeçalho no cabeçalho da ponte:
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"
Aqui está o vídeo original explicando isso
__OBJC
seleção para o seu Bridging-cabeçalho, por exemplo#ifdef __OBJC @import UIKit; #endif
Parece ser uma cera de bola bastante diferente quando se lida com ponteiros. Aqui está o que tenho até agora para chamar a read
chamada de 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
}