Answers:
是的,您当然可以与Apples C库进行交互。这里说明了如何。
基本上,C型,C指针等被翻译成对象斯威夫特,例如C int
在夫特是一个CInt
。
我为另一个问题构建了一个小例子,该例子可以作为对C和Swift之间的桥梁:
主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);
这是原始答案。
编译器将C API转换为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)
}
请参阅文档中的与Objective-C API交互。
CFTypeRef
)转换为Swift对象。不过,大多数ObjCRuntime.h函数对Swift都没有意义。
万一您和我一样不熟悉XCode,并想尝试Leandro的答案中发布的摘录:
它是针对如何对CommonCrypto项目执行此操作而构建的,但通常,它应可用于您要在Swift中使用的任何其他C库。
我简要地尝试过为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 *
}
然后在Targets-> Link Binary With Libraries下,我选择添加项目并添加libz.tbd。
您可能要在此时进行构建。
然后,我能够编写以下代码:
import zlib
public class Zlib {
public class func zlibCompileFlags() -> UInt {
return zlib.zlibCompileFlags()
}
}
你不具备把zlib库的名字在前面,除了在命名雨燕类FUNC一样的C函数上述情况下,我,没有资格雨燕FUNC最终被重复调用,直到应用程序暂停。
对于c ++,会弹出此错误:
"_getInput", referenced from:
您还需要一个c ++头文件。将c链接添加到您的函数中,然后将头文件包括在bridge-header中:
迅捷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);
}
主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
}