Câu trả lời:
Có, tất nhiên bạn có thể tương tác với các thư viện Táo C. Dưới đây là giải thích như thế nào.
Về cơ bản, các loại C, con trỏ C, v.v ... được dịch thành các đối tượng Swift, ví dụ: C int
trong Swift là a CInt
.
Tôi đã xây dựng một ví dụ nhỏ, cho một câu hỏi khác, có thể được sử dụng như một lời giải thích nhỏ, về cách kết nối giữa C và Swift:
chính
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);
Đây là câu trả lời ban đầu.
Trình biên dịch chuyển đổi API C thành Swift giống như đối với Objective-C.
import Cocoa
let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
import Darwin
for _ in 1..10 {
println(rand() % 100)
}
Xem Tương tác với API khách quan-C trong tài liệu.
CFTypeRef
được chuyển đổi thành đối tượng Swift. Mặc dù vậy, hầu hết các hàm ObjCR nb.h không có ý nghĩa đối với Swift.
Chỉ trong trường hợp bạn là người mới với XCode như tôi và muốn thử các đoạn được đăng trong câu trả lời của Leandro :
Bài đăng này cũng có một lời giải thích tốt về cách thực hiện điều này bằng cách sử dụng hỗ trợ mô-đun của clang .
Nó đóng khung về cách thực hiện điều này cho dự án CommonCrypto, nhưng nói chung, nó sẽ hoạt động cho bất kỳ thư viện C nào khác mà bạn muốn sử dụng từ trong Swift.
Tôi đã thử nghiệm ngắn gọn với việc làm điều này cho zlib. Tôi đã tạo một dự án khung iOS mới và tạo một thư mục zlib, chứa tệp module.modulemap với các mục sau:
module zlib [system] [extern_c] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/zlib.h"
export *
}
Sau đó, trong mục tiêu -> Liên kết nhị phân với thư viện tôi đã chọn thêm các mục và thêm libz.tbd.
Bạn có thể muốn xây dựng tại thời điểm này.
Sau đó tôi đã có thể viết mã sau đây:
import zlib
public class Zlib {
public class func zlibCompileFlags() -> UInt {
return zlib.zlibCompileFlags()
}
}
Bạn không cần phải đặt tên thư viện zlib ở phía trước, ngoại trừ trong trường hợp trên tôi đã đặt tên cho lớp Swift giống như hàm C và không có đủ điều kiện, func Swift kết thúc được gọi liên tục cho đến khi ứng dụng dừng lại.
Trong trường hợp của c ++, có lỗi này bật lên:
"_getInput", referenced from:
Bạn cũng cần một tệp tiêu đề c ++. Thêm liên kết c vào chức năng của bạn, sau đó đưa tệp tiêu đề vào tiêu đề cầu nối:
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);
}
chính
import Foundation
var output: CInt = 0
getInput(&output)
print(output)
cliinput-Bridging-Header.h
#include "UserInput.h"
Đây là video gốc giải thích điều này
__OBJC
séc cho bạn Bridging-Header, ví dụ:#ifdef __OBJC @import UIKit; #endif
Nó dường như là một quả bóng khá khác biệt khi tiếp xúc với con trỏ. Đây là những gì tôi có cho đến nay để gọi cuộc gọi read
hệ thống 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
}