【问题标题】:Swift / C interop, struct data change in Swift not updating back in CSwift / C 互操作,Swift 中的结构数据更改未在 C 中更新
【发布时间】:2020-09-14 12:00:00
【问题描述】:

我有一个 C 结构

struct Test {
  int a;
}

typedef struct Test Test;

在 C 中我创建了一个指针,

Test* myTestPointer = new Test();

我在 Swift 中获得了结构指针 myTestPointer,并且我检查了该指针确实在 Swift 和 C 中都指向正确的地址。

但我很难理解为什么以下两段代码不等同于 C 代码中 a 的值衡量?

let x = myTestPointer
x!.pointee.a = 123     // correctly changes the memory, as reflected back in C code
var x = myTestPointer!.pointee
x.a = 123  // does not reflect change back in C code

【问题讨论】:

  • C 和 C++ 是不同的语言。

标签: c swift pointers struct


【解决方案1】:

将表达式 myTestPointer!.pointeeTest) 类型)赋值给变量 x 会导致结构体的副本。

x.a 的更改会影响此副本,但不会影响指针指向的副本。

实际上,结构副本真的经常被优化器完全碰撞,但在这种情况下,我认为总是会发生副本,因为指针可以像一个黑盒子一样,可以实现任何方式的外部状态观察/突变。

在任何情况下,您都不应该尝试通过共享状态的突变来在 Swift 和 C 之间(或者坦率地说,在任何软件系统的任何两个组件之间)来回传达状态差异。当然,出于性能原因,有时您需要构建其他通信原语(例如,在进程之间构建消息队列,由底层共享内存区域支持),但一般来说,这种方法是在乞求竞争条件和奇怪的同步困难.

【讨论】:

  • 我想它一定是这样的。是的,不理想,但我的游戏引擎需要这个,它有一个 C++ 核心,在 iOS/Swift 和 Android/Kotlin(或任何其他支持 C/C++ 的语言)之间共享。这是我能看到编写多平台游戏同时保持出色效率/速度的唯一方法。不过,我可能会重新考虑是否有一种更安全的方法来更新数据,而无需编写大量的 setter 函数,而不是使用我目前获取结构并直接更新内存的方法。
  • (我要说的一切都有很大的警告,一如既往地衡量并根据需要进行权衡)通常游戏状态/逻辑足够快,与图形相比,它不是主要瓶颈渲染事物的一面。事实上,在反应流(观察者/发布者)、通知等方面,您可能能够负担得起很多奢侈品。如果您确实想采用变异共享内存方法进行更新,我将在 Swift 端将其建模为包含指向游戏状态的指针的结构上的函数。每个 fn 都会取消引用指针并就地编辑。
  • 是的,我想这是一个权衡利弊的案例。只要我对内存管理以及渲染/UI线程如何处理我的游戏数据很挑剔,我应该没问题。我确实认为编写一个 Swift 版本和一个 Kotlin 版本以及一个 What-else 版本会很好,但我必须在某个地方划清界限。对其中一个的更改意味着我需要更改所有其他的,所以我选择了 C/C++ 路线。我非常喜欢变异共享内存方法,但正如 Swift 不断提醒我的那样,我最终会使用 Unsafe 指针。
  • @Pixel 如果您使用像我提到的那样的“网关”对象,不安全的指针会隐藏在其令人愉悦的外观背后(movePieceTo(x:y:)castleQueenSide() 等)。你只需要确保参考内存比你的小 Swift 外观更长寿。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 2023-02-18
  • 2017-07-15
相关资源
最近更新 更多