【问题标题】:How to return UnsafePointer <CChar> and UnsafePointer <CUnsignedInt> with Swift如何使用 Swift 返回 UnsafePointer <CChar> 和 UnsafePointer <CUnsignedInt>
【发布时间】:2015-04-27 19:28:27
【问题描述】:

我正在编写一个需要与 C 库互操作的 Swift 程序。 这个 C 库由一组使用回调的函数组成。 我解决了如何将 Swift func 传递给这些 C 函数的问题,但是我在将 Swift 本机类型转换为适当的 C 类型时遇到了困难。

具体来说,我有这 2 个回调(签名必须是这个才能被 C 库接受):

func peer_name_handler_swift_test(p: peer_wr) -> UnsafePointer<CChar>
{
    return nil;
}

func peer_ver_handler_swift_test(p: peer_wr) -> UnsafePointer<CUnsignedInt>
{
    return nil;
}

好吧,尽管我努力了,我还是无法从 String Swift 类型和简单的 CUnsignedInt 数组返回正确的类型。

我想在这些回调中返回的 2 个数据是:

var BLZ_SWIFT_TEST_PEER_VER: [CUnsignedInt] = [0,0,1,0];
var BLZ_SWIFT_TEST_PEER_NAME: String = "test_swift_peer";

你能帮帮我吗?

【问题讨论】:

    标签: c swift callback type-conversion


    【解决方案1】:

    可以通过多种方式将数据强制转换为正确的指针类型。这个问题的棘手部分是决定如何管理你给出一个指针的内存。

    如果你在编译时声明静态已知的值,你可以这样做:

    // I _think_ you need to manually null-terminate the string here 
    let BLZ_SWIFT_TEST_PEER_NAME: StaticString = "test_swift_peer\0"
    
    func peer_name_handler_swift_test(p: peer_wr) -> UnsafePointer<CChar>
    {
        return UnsafePointer(BLZ_SWIFT_TEST_PEER_NAME.utf8Start)
    }
    
    // tuples are the closest approximation to C fixed-size arrays
    var BLZ_SWIFT_TEST_PEER_VER 
             = (0,0,1,0) as (CUnsignedInt,CUnsignedInt,CUnsignedInt,CUnsignedInt)
    
    func peer_ver_handler_swift_test(p: peer_wr) -> UnsafePointer<CUnsignedInt>
    {
        return withUnsafePointer(&BLZ_SWIFT_TEST_PEER_VER) {
            UnsafePointer($0)
        }
    }
    

    两个函数体中额外出现的UnsafePointer 是指针转换。在字符串的情况下,因为utf8UInt8CCharInt8 的别名。在数组的情况下,因为你想要一个指向第一个 CUnsignedInt 的指针而不是一个指向 4 元组的指针。

    如果您想在运行时更改值,您需要决定谁将创建/释放内存,是否需要分配多位内存,因为回调的调用者将存储指针,然后如果你改变它,你将需要分配一个新的内存,而不是覆盖你已经分发的内存等等,如果是这样,你如何跟踪它以便以后释放它以避免泄漏。如果你想要一个静态字符串,但你想在运行时创建一个,比如从一个配置文件,你可以这样做:

    // prior to the callback getting called
    let namePtr = strdup(BLZ_SWIFT_TEST_PEER_NAME)
    
    func peer_name_handler_swift_test(p: peer_wr) -> UnsafePointer<CChar>
    {
        return UnsafePointer(namePtr)
    }
    
    // then some time later, if you want to clean up
    free(namePtr)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 1970-01-01
      相关资源
      最近更新 更多