在 Swift 中初始化 C 结构体

Posted

技术标签:

【中文标题】在 Swift 中初始化 C 结构体【英文标题】:Initializing C structs in Swift 【发布时间】:2014-08-03 23:43:46 【问题描述】:

我在从 Swift 调用 statfs() 时遇到问题。该调用使用一个也称为 statfs 的结构作为参数,而 swift 编译器似乎将两者混淆了。

这段代码告诉我该结构未初始化,因此无法编译:

var sb : statfs
if(statfs(fd, &sb) == 0)

    //...

但是当我尝试初始化结构时(我尝试过 "var sb : statfs = statfs()" 和 "var sb : statfs = statfs(f_bsize: 0, f_iosize: 0, ...)" ,它告诉我参数不匹配,它似乎在寻找函数的参数而不是结构。

所以,我猜我必须缺少一些语法糖,才能让编译器意识到它应该查看结构而不是函数。

我有一个类似的命名问题,这更让人不便:我想有一个名为 open() 的类,它调用 posix 命令 open(),但我无法让编译器意识到我想要调用 posix 命令而不是我自己的方法。我通过简单地重命名我的方法来解决这个问题,但是当存在多个同名项目时,必须有一些语法让编译器知道你指的是哪个项目。

【问题讨论】:

【参考方案1】:

问题在于 Swift 将函数名和结构名都导入为statfs。您可以通过 typealias 消除它们的歧义。

/// universal initializer
func blankof<T>(type:T.Type) -> T 
    var ptr = UnsafeMutablePointer<T>.alloc(sizeof(T))
    var val = ptr.memory
    ptr.destroy()
    return val

import Darwin
typealias StatFS = statfs // this does the trick
var fs = blankof(StatFS)
println(statfs("/", &fs))
println(fs.f_ffree)

【讨论】:

这很好用!但是,在查看文档后: UnsafeMutablePointer.alloc 的参数是 T 的多个值,而不是字节 - 所以这里应该是“1”。此外,ptr.move() 被记录为与 .memory 和 .destroy() 执行相同的操作,但速度更快,因此您可以将其减少到一行。【参考方案2】:

关于你的第二个问题(你应该把它单独做一个吗?;-):

我希望有一个名为 open() 的类,它调用 posix 命令 open(),但我无法让编译器意识到我想调用 posix 命令而不是我自己的方法。

试试这个:

func open(x, y) 
  Darwin.open(x, y)

就像在这里: https://github.com/AlwaysRightInstitute/SwiftSockets/blob/master/ARISockets/Socket.swift#L99

【讨论】:

以上是关于在 Swift 中初始化 C 结构体的主要内容,如果未能解决你的问题,请参考以下文章

Swift 结构体和类的区别

Swift开发注意点

观察 Swift 结构体的变化

Swift Struct 结构体

c语言结构体初始化

Swift Classstruct