我正在开发一个涉及使用我从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)
如何解决这个问题?谢谢。
答案 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
这是一种比下面更通用的方法,但您需要明确TargetStruct
和func 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 ...
希望您能找到最佳解决方案。