【问题标题】:How can I use Swift objects as UnsafeMutablePointer<OpaquePointer?> to a C function如何将 Swift 对象用作 C 函数的 UnsafeMutablePointer<OpaquePointer?>
【发布时间】:2020-03-28 08:57:45
【问题描述】:

有一个 C 结构体:

struct SomeStruct;

还有一个 C 函数使用这个结构作为双指针参数:

C_exampleFunction(struct SomeStruct** someClass)

我想将任何 Swift 类或对象传递给这个函数,以便使用它的功能。但是 Swift 端的 C 函数只接受 UnsafeMutablePointer 作为参数:

mySwiftFunction(for obj: AnyObject) {
   let objUnsafeMutableRawPointer = Unmanaged.passUnretained(obj).toOpaque()
   let objOpaquePointer = OpaquePointer(objUnsafeMutableRawPointer)
   let someClassArg = UnsafeMutablePointer<OpaquePointer?>(objOpaquePointer)

   C_exampleFunction(someClassArg)
}

即使我解除分配指针,代码也总是会产生一些内存错误。 我的主要问题是如何将对象作为 UnsafeMutablePointer 添加到上面这样的 C 函数中?

我检查了这些来源(但没有运气):

我得到的错误是:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x6ba571ac0)

感谢您的回答、反馈,尤其是您提前提供的时间。

【问题讨论】:

  • 使用 void 指针将引用传递给结构。然后在函数中你可以根据需要使用它
  • 嘿@P__J__ 感谢您的快速回复。但是不确定我是否明白。什么类型的 Void 指针是什么意思? Swift 端的函数只接受具有 UnsafeMutablePointer 类型的参数。
  • 我不确定我是否理解这个问题。 C 函数签名意味着它需要 **SomeStruct。那个结构是什么? “任何 Swift 类或对象”如何与该结构相关联?如果你使用 void ptr 来传递一个 Swift 对象,那么 C 函数在它可以做的事情上仍然非常有限。
  • 同意感觉您正在跳过问题的某些关键部分。您不能将任意指针传递给期望struct SomeStruct** 的东西。这里的语言无关紧要。类型必须匹配或如何工作。因此,如果您将随机类型传递给 mySwiftFunction,则不清楚它是如何工作的。您的 mySwiftFunction 函数也没有定义行为(您不能在 Swift 中以这种方式创建指针)。这个函数期望什么样的结构,为什么你认为你可以向它传递任意类型?
  • 抱歉回复晚了。首先感谢您的时间和帮助,特别是专门的答案。你是对的,这里的问题是缺少一个重要信息。我从一个 C 库中获得了这个函数,我想在一个用 Swift 编写的项目中使用它。这主要是一个问题,我是否可以这样使用它?因为我可以使用该方法的唯一方法是我以某种方式使用此 OpaquePointer。关于这个方法,我唯一知道的是我只能向它添加对象,并且它使用结构类型双指针。

标签: c swift pointers unsafemutablepointer


【解决方案1】:

我认为通过不完整的类型指针传递给 C 函数的 Swift 对象可以做的事情相对较少,但如果你需要这样做,那么你就在正确的轨道上。

我在您问题中的代码中看到的一个问题是行

let someClassArg = UnsafeMutablePointer<OpaquePointer?>(objOpaquePointer)

这里的someClassArg 仍然是一个指向obj 的指针,它被传递给mySwiftFunction(),它只是被转换为不同的指针类型。然而,C_exampleFunction() 需要一个指向obj 的指针。因此代码很可能会崩溃。

您可以通过将有问题的行替换为

来解决此问题
let someClassArg = UnsafeMutablePointer<OpaquePointer?>.allocate(capacity: 1)
someClassArg.pointee = objOpaquePointer

还有其他方法。例如,您可以使用inout 语法传递objOpaquePointer;不过,它必须是 var 才能工作。你也可以避免像这样使用Unmanaged

let objUnsafeMutablePtr = UnsafeMutablePointer<AnyObject>.allocate(capacity: 1)
objUnsafeMutablePtr.pointee = obj
var objOpaquePtr : OpaquePointer! = OpaquePointer(objUnsafeMutablePtr)
C_exampleFunction(&objOpaquePtr) 

(这里我们将不透明指针作为inout 传递)。

无论采用哪种方法,都应该非常小心obj 的生命周期。例如,如果您使用Unmanaged,您可能希望使用passRetained()(然后在检索对象时使用takeRetainedValue()),但这取决于您的用例。

这是另一个关于手动内存管理的有用资源:

https://developer.apple.com/documentation/swift/swift_standard_library/manual_memory_management

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多