gpt4 book ai didi

objective-c - 具有 Swift 结构的 C API - 作为 inout 参数的不可变值

转载 作者:太空宇宙 更新时间:2023-11-04 03:21:31 26 4
gpt4 key购买 nike

我正在从事一个 Swift 3 项目,该项目涉及使用我从 Objective-C 桥接的一些 C API。

这是 API 结构的示例片段:

typedef struct
{
StructMode mode;
StructLevel level;
} TargetStruct;

typedef struct
{
. . .
TargetStruct *targetStruct;
OtherStruct *otherStruct;
NonPointerStructA nonPointerStructA;
NonPointerStructB nonPointerStructB;
. . .
} InnerStruct;

typedef struct
{
InnerStruct innerStruct;
OtherStructB otherStructB;
} OuterStruct;

在我的 Swift 代码中,我的目标是从 OuterStruct 设置 TargetStruct 的值,如下所示:

// run function that returns an instance of TargetStruct
var targetStruct: TargetStruct = initializeTargetStruct()

// assign targetStruct to outerStruct
outerStruct.innerStruct.targetStruct = &targetStruct

但是,我收到以下错误:

Cannot pass immutable value of TargetStruct as inout argument

如果我设置一个没有 * 的结构值,它会正常工作:

var nonPointerStructA: NonPointerStructA = initializeNonPointerStructA()
outerStruct.innerStruct.nonPointerStructA = nonPointerStructA

我试过像这样设置 targetStruct 的值,但目前我无法测试它:

var targetStruct: TargetStruct = initializeTargetStruct()
outerStruct.innerStruct.targetStruct.initialize(from: &targetStruct, count: 0)

如何解决这个问题?谢谢。

最佳答案

在 Swift 中,前缀 & 不是 address-of 运算符。只需要澄清一些表达式被传递给 inout 参数。因此,您的第一个代码在 Swift 中在语法上是无效的。

你的 C 结构被导入 Swift 如下:

struct TargetStruct {
var mode: StructMode
var level: StructLevel

//some auto generated initializers...
}

struct InnerStruct {
//...
var targetStruct: UnsafeMutablePointer<TargetStruct>!
var otherStruct: UnsafeMutablePointer<OtherStruct>!
var nonPointerStructA: NonPointerStructA
var nonPointerStructB: NonPointerStructB

//some auto generated initializers...
}

struct OuterStruct {
var innerStruct: InnerStruct
var otherStructB: OtherStructB

//some auto generated initializers...
}

(如果有不对的地方,请告诉我。)

如您所见,InnerStruct 中的targetStruct 是一个指针,initialize(from:count:) 尝试写入指向的指针region,但是在你调用 initialize(from:count:) 时,targetStruct 保持它的初始值 nil,你知道解引用时会发生什么空指针。


一种方法是为TargetStruct 分配内存并使用指向分配区域的指针。

func allocateAndInitializeTargetStruct() -> UnsafeMutablePointer<TargetStruct> {
let targetStructRef = UnsafeMutablePointer<TargetStruct>.allocate(capacity: 1)
targetStructRef.initialize(to: initializeTargetStruct())
return targetStructRef
}

outerStruct.innerStruct.targetStruct = allocateAndInitializeTargetStruct()

这是一种比下面更通用的方法,但是您需要显式地取消初始化取消分配 分配的区域。这有点难以管理。


如果您可以将 outerStruct 的使用限制在单个代码块中,您可以这样写:

var targetStruct = initializeTargetStruct()
withUnsafeMutablePointer(to: &targetStruct) {targetStructPtr in
outerStruct.innerStruct.targetStruct = targetStructPtr

//Use `outerStruct` only inside this code-block
//...
}

在这种情况下,outerStruct.innerStruct.targetStruct (== targetStructPtr) 中保存的指针仅在闭包内部有效,不能在闭包外部使用。


如果上述任何代码不适合您的用例,您可能需要提供更多上下文以找到最佳解决方案。


嵌套使用 withUnsafeMutablePointer(to:_:) 的示例:

var targetStruct = initializeTargetStruct()
var otherStruct = initializeOtherStruct()
withUnsafeMutablePointer(to: &targetStruct) {targetStructPtr in
withUnsafeMutablePointer(to: &otherStruct) {otherStructPtr in
outerStruct.innerStruct.targetStruct = targetStructPtr
outerStruct.innerStruct.otherStruct = otherStructPtr

//Use `outerStruct` only inside this code-block
//...
}
}

当你需要设置更多的指针时,这种嵌套会很困惑,但这是 Swift 目前的局限性。


deinitializedeallocate 的例子:

extension InnerStruct {
func freeMemberStructs() {
if let targetStructRef = targetStruct {
targetStructRef.deinitialize()
targetStructRef.deallocate(capacity: 1)
targetStruct = nil
}
if let otherStructRef = otherStruct {
otherStructRef.deinitialize()
otherStructRef.deallocate(capacity: 1)
otherStruct = nil
}
}
}

outerStruct.innerStruct.targetStruct = allocateAndInitializeTargetStruct()
outerStruct.innerStruct.otherStruct = allocateAndInitializeOtherStruct()

// Use `outerStruct`
//...

outerStruct.innerStruct.freeMemberStructs()

代码似乎并不太复杂(只是一堆样板代码),但很难找到何时何地执行此操作。由于您的 InnerStruct 可能嵌入到另一个可能需要 deinitilized 和 deallocated...

的结构中

希望您能找到最佳解决方案。

关于objective-c - 具有 Swift 结构的 C API - 作为 inout 参数的不可变值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45605309/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com