【问题标题】:How to create instance of Swift type UnsafePointer<UnsafePointer<Int8>?>! to pass to C function如何创建 Swift 类型 UnsafePointer<UnsafePointer<Int8>?> 的实例!传递给 C 函数
【发布时间】:2020-08-26 08:14:18
【问题描述】:

我正在尝试从 Swift 调用 C 函数

C 函数的参数之一被定义为类型:

const char * const * i_argv

在 Xcode 中,自动完成将其映射到 Swift 类型:

_ i_argv: UnsafePointer&lt;UnsafePointer&lt;Int8&gt;?&gt;!

我创建这种类型的实例的所有尝试都失败了

我想传递一个包含两个 Int8 的数组

let args: [Int8] = [ 1, 1 ]

如果我直接通过,我会得到错误:

cannot convert value of type 'UnsafePointer&lt;Int8&gt;' to expected argument type 'UnsafePointer&lt;UnsafePointer&lt;Int8&gt;?&gt;'

然后我尝试将数组包装在外部 UnsafePointer 中

let argsp: UnsafePointer&lt;Optional&lt;UnsafePointer&lt;Int8&gt;&gt;&gt; = UnsafePointer(args)

但这似乎没有按预期工作并给出错误:

cannot assign value of type 'UnsafePointer&lt;Int8&gt;' to type 'UnsafePointer&lt;Optional&lt;UnsafePointer&lt;Int8&gt;&gt;&gt;'

我不知道如何用外部 UnsafePointer 包装数组的 UnsafePointer 类型

编辑:

来自 C 项目的示例:

    #define FIB_ARG_VALUE  "40"
    const char* i_argv[2] = { FIB_ARG_VALUE, NULL };
    result = m3_CallWithArgs (f, 1, i_argv);

根据您的评论,我设法让 Swift 代码使用以下参数构造进行编译(只是一个编译测试)

let argsp: [UnsafePointer&lt;Int8&gt;?] = [ UnsafePointer([1,2,3]), UnsafePointer("40".cString(using: String.Encoding.utf8)) ]

这仍然会发出有关创建悬空指针的警告

【问题讨论】:

  • 当参数类型为UnsafePointer&lt;UnsafePointer&lt;Int8&gt;?&gt;!时,需要传入UnsafePointer&lt;Int8&gt;?的Array。所以,想要传递一个包含两个 Int8 的数组 是没有意义的。你能展示一下 C 中函数的示例用法吗?
  • 更新原帖
  • 感谢更新,能否说明FIB_ARG_VALUE 是如何定义的?
  • 添加了 FIB_ARG_VALUE 定义和 args 的编译(带有警告)版本。

标签: c swift unsafe-pointers


【解决方案1】:

正如我在评论中所写,

当参数类型为UnsafePointer&lt;UnsafePointer&lt;Int8&gt;?&gt;!时,需要传入UnsafePointer&lt;Int8&gt;?的Array。

在您重新更新的部分中,您了解该部分传递UnsafePointer&lt;Int8&gt;?的数组,但您未能创建数组的每个元素。

与您的 C 项目中的示例 等效的 Swift 将是:

let FIB_ARG_VALUE = "40"
let result: CInt = FIB_ARG_VALUE.withCString {pointer in
    let i_argv: [UnsafePointer<Int8>?] = [
        pointer,
        nil
    ]
    return m3_CallWithArgs(f, 1, i_argv)
}

编译测试代码的正确方法应该如下所示:

let arg1: [Int8] = [1,2,3]
let arg2: String = "40"
_ = arg1.withUnsafeBufferPointer {arg1BufPtr in
    arg2.withCString {arg2Ptr in
        let argsp: [UnsafePointer<Int8>?] = [ arg1BufPtr.baseAddress,
            arg2Ptr
        ]
        //Use `argsp` inside this block.
        //...
    }
}

在这两种情况下,我假设您的 C 函数不会保留在 i_argv 中传递的指针以供将来使用,否则您需要进行一些修改才能将内容复制到某个稳定地址。

或者您需要根据实际参数或 C 函数的功能来修改其他一些部分。

【讨论】:

    猜你喜欢
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多