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

时间:2017-08-10 05:41:36

标签: objective-c c swift struct

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

以下是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)

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

1 个答案:

答案 0 :(得分:1)

在Swift中,前缀$remote_lpc0 = "10.53.216.28" $password0 = ConvertTo-SecureString "yt_xk39b"-AsPlainText -Force $cred0 = New-Object Management.Automation.PSCredential("reglpc", $password0) Invoke-Command -ComputerName $remote_lpc0 -Credential $cred0 -ScriptBlock { C:\GIT\registers_e2e\HLRPerformanceScripts\common\start.bat } echo "hello" 不是地址 - 运算符。只需要澄清一些表达式传递给&参数。所以,你的第一个代码在Swift中在语法上是无效的。

您的C结构导入Swift,如下所示:

inout

(如果出现问题,请告诉我。)

如您所见,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... } 中的targetStruct是指针,InnerStruct尝试写入指向的区域,但在您拨打initialize(from:count:)时,{ {1}}保持其初始值initialize(from:count:),您知道解除引用空指针时会发生什么。

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

nil

这是一种比下面更通用的方法,但您需要明确TargetStructfunc allocateAndInitializeTargetStruct() -> UnsafeMutablePointer<TargetStruct> { let targetStructRef = UnsafeMutablePointer<TargetStruct>.allocate(capacity: 1) targetStructRef.initialize(to: initializeTargetStruct()) return targetStructRef } outerStruct.innerStruct.targetStruct = allocateAndInitializeTargetStruct() 分配的区域。这有点难以管理。

如果你可以在一个代码块中限制deinitialize的用法,你可以这样写:

deallocate

在这种情况下,outerStruct(== var targetStruct = initializeTargetStruct() withUnsafeMutablePointer(to: &targetStruct) {targetStructPtr in outerStruct.innerStruct.targetStruct = targetStructPtr //Use `outerStruct` only inside this code-block //... } )中的指针只在闭包内有效,你不能在它之外使用它。

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

嵌套使用outerStruct.innerStruct.targetStruct

的示例
targetStructPtr

当你需要更多指针设置时,这个嵌套会很乱,但这是Swift的当前限制。

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 //... } } 的一个例子:

deinitialize

代码似乎不太复杂(只是一堆样板代码),但很难找到何时或何地执行此操作。由于您的deallocate可能会嵌入另一个可能需要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() d和InnerStruct d ...

的结构中

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