Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Swift呼叫C?_C_Swift - Fatal编程技术网

如何从Swift呼叫C?

如何从Swift呼叫C?,c,swift,C,Swift,有没有办法从Swift调用C例程 很多iOS/Apple库都是C语言的,我仍然希望能够调用它们 例如,我希望能够从swift调用objc运行库 特别是,如何桥接iOS C头?是的,您当然可以与苹果的C库交互。是如何解释的 基本上,C类型、C指针等被转换为Swift对象,例如Swift中的Cint就是一个CInt 我为另一个问题建立了一个小例子,这个问题可以作为一个小解释,关于如何在C和Swift之间架起桥梁: main.swift import Foundation var output: C

有没有办法从Swift调用C例程

很多iOS/Apple库都是C语言的,我仍然希望能够调用它们

例如,我希望能够从swift调用objc运行库


特别是,如何桥接iOS C头?

是的,您当然可以与苹果的C库交互。是如何解释的

基本上,C类型、C指针等被转换为Swift对象,例如Swift中的C
int
就是一个
CInt

我为另一个问题建立了一个小例子,这个问题可以作为一个小解释,关于如何在C和Swift之间架起桥梁:

main.swift

import Foundation

var output: CInt = 0
getInput(&output)

println(output)
import Foundation
var output: CInt = 0
getInput(&output)
print(output)
UserInput.c

#include <stdio.h>

void getInput(int *output) {
    scanf("%i", output);
}
#include <stdio.h>

void getInput(int *output) {
    scanf("%i", 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)
}

请参阅文档中的内容。

以防您和我一样不熟悉XCode,想要尝试发布在中的代码片段:

  • 文件->新建->项目
  • 选择命令行工具作为项目预设,并将项目命名为“cliinput”
  • 右键单击项目导航器(左侧的蓝色面板)并选择“新建文件…”
  • 在下拉对话框中,将文件命名为“UserInput”。取消选中“同时创建头文件”框。单击“下一步”后,将询问XCode是否应为您创建桥接头.h文件。选择“是”
  • 复制并粘贴上面Leandro答案中的代码。单击play按钮后,它应该在终端中编译并运行,xcode中的终端内置在底部面板中。如果在终端中输入一个数字,将返回一个数字
  • 也有一个关于如何使用clang的很好的解释

    它的框架是关于如何为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->linkbinary With Libraries下,我选择additems并添加libz.tbd

    此时您可能需要构建

    然后,我能够编写以下代码:

    import zlib
    
    public class Zlib {
        public class func zlibCompileFlags() -> UInt {
            return zlib.zlibCompileFlags()
        }
    }
    

    您不必将zlib库名称放在前面,除非在上述情况下,我将Swift类func命名为与C函数相同的名称,并且在没有限定条件的情况下,Swift func最终会被重复调用,直到应用程序停止。

    在处理指针时,它似乎是一个完全不同的ball'o wax。以下是我到目前为止调用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
    }
    
    enum FileReadableStreamError:错误{
    案例失败重新阅读
    }
    //一些帮助来自:http://stackoverflow.com/questions/38983277/how-to-get-bytes-out-of-an-unsafemutablerawpointer
    //及https://gist.github.com/kirsteins/6d6e96380db677169831
    重写函数读取字节(大小:UInt32)抛出->[UInt8]?{
    guard let unsafeMutableRawPointer=malloc(Int(size))else{
    归零
    }
    让numberBytesRead=read(fd,unsafeMutableRawPointer,Int(size))
    如果numberBytesRead<0{
    自由(非女性化指针)
    抛出FileReadableStreamError.failedOnRead
    }
    如果numberBytesRead==0{
    自由(非女性化指针)
    归零
    }
    让unsafeBufferPointer=unsafeBufferPointer(开始:unsafeMutableRawPointer.assumingmemorybind(to:UInt8.self),计数:numberbytes读取)
    让结果=数组(unsafeBufferPointer)
    自由(非女性化指针)
    返回结果
    }
    
    > p>在C++的情况下,出现了这个错误:

      "_getInput", referenced from: 
    

    你也需要一个C++头文件。添加到函数中,然后将头文件包括在桥接头中:

    Swift 3

    UserInput.h

    void getInput(int *output);
    
    #ifndef USERINPUT_H
    #define USERINPUT_H    
    
    #ifdef __cplusplus
    extern "C"{
    #endif
    
    getInput(int *output);
    
    #ifdef __cplusplus
    }
    #endif
    
    #include "UserInput.h"
    
    UserInput.c

    #include <stdio.h>
    
    void getInput(int *output) {
        scanf("%i", output);
    }
    
    #include <stdio.h>
    
    void getInput(int *output) {
        scanf("%i", output);
    }    
    
    cliinput桥接头.h

    void getInput(int *output);
    
    #ifndef USERINPUT_H
    #define USERINPUT_H    
    
    #ifdef __cplusplus
    extern "C"{
    #endif
    
    getInput(int *output);
    
    #ifdef __cplusplus
    }
    #endif
    
    #include "UserInput.h"
    

    这是原稿

    谢谢你的例子,你说得对,我可以看出这是怎么回事。然而,它并没有真正回答我的问题,即如何调用apple C库。但这绝对是最接近的。看看文件的其他地方。例如,CoreFoundation样式的“对象”(
    CFTypeRef
    )将转换为Swift对象。但是,大多数ObjCRuntime.h函数对Swift没有意义?我想我需要找到一些方法导入一个标题并桥接它。这看起来很尴尬,但我想应该是这样。我对ios/swift还不熟悉。我想使用swift文件中包含的日志c函数。任何人?它与C++、.CPP文件兼容吗?直接使用C++文件,应该创建Objto-C包装器。您希望实现(它本身应该驻留在.mm文件中)包含Objto-C++代码(它只是一个文件中的Objto-C和C++),接口(应该在它自己的.h头文件)中应该包含纯ObjuleC代码,因此您必须在实现中将C++类型转换为Objy-C类型,把他们暴露给斯威夫特。然后,您可以使用objective-c桥接头导入该头。“您当然可以与Apple c库交互”不正确。您可以与任何C库进行交互,完全不限于Apple的。更新的文档链接如果不起作用,请尝试将
    \uuuuuujc
    检查添加到桥接头,例如
    \ifdef\uuuuuujc@import UIKit#endif