简体   繁体   English

如何安全正确地将 [[T]] 转换为 UnsafePointer <UnsafePointer<T> &gt; 暂时

[英]How do I safely and correctly convert [[T]] to UnsafePointer<UnsafePointer<T>> temporarily

I need to call C functions that take 2d arrays.我需要调用采用二维数组的 C 函数。 The future arrays are created in Swift, and are generally [String] , but I'm interested in the [[T]] case too.未来的数组是在 Swift 中创建的,通常是[String] ,但我对[[T]]情况也很感兴趣。

The API I'm calling specifies that its functions always copy data passed to them if necessary, so I don't want create a copy of the contents myself just to pass it in, and I only need to worry about the pointers being valid until I can pass them into the C functions.我正在调用的 API 指定它的函数总是在必要时复制传递给它们的数据,所以我不想自己创建内容的副本只是为了传递它,我只需要担心指针直到我可以将它们传递给 C 函数。 My current approach is to do我目前的做法是

    let addressArray = someArray.map { (array) in
        array.withUnsafeBufferPointer({ (buffer) in
            // get an array of addresses to each individual member
            return buffer.baseAddress
        })
    }

addressArray.withUnsafeBufferPointer { bufferPointer in
     someCFunction(bufferPointer.baseAddress)
     // do something with someArray to attempt to ensure that the pointers are valid past the lifetime of the withUnsafeBufferPointer call
}

This works, but as the pointers returned from withUnsafeBufferPointer are said to only be valid in that scope, it's clearly wrong (though by being certain to always require that someArray remain alive until after I'm done with someCFunction I feel fairly confident that it won't break in the short term).这是有效的,但由于从withUnsafeBufferPointer返回的指针据说仅在该范围内有效,这显然是错误的(尽管通过确定始终要求someArray保持活动状态,直到我完成someCFunction我感到相当有信心它赢了短期内不会中断)。 But there must be a better way;但一定有更好的方法; what is it?它是什么?

As you have experienced, your code would seemingly work occasionally.正如您所经历的那样,您的代码似乎偶尔会起作用。 But as you have written, your code is wrong as the returned pointers from withUnsafeBufferPointer is valid only in the scope of its closure parameter.但是正如您所写的,您的代码是错误的,因为从withUnsafeBufferPointer返回的指针仅在其闭包参数的范围内有效。

And I do not understand what you mean it won't break in the short term , but I recommend you never to be confident about undocumented and unclear behaviors.我不明白你的意思是短期内不会中断,但我建议你永远不要对无证和不清楚的行为充满信心。

You may need to create some stable pointers, you can achieve that by allocating the regions explicitly.您可能需要创建一些稳定的指针,您可以通过显式分配区域来实现。

I would write something like this when I need UnsafePointer<UnsafePointer<T>> to pass the content of nested Array [[T]] .当我需要UnsafePointer<UnsafePointer<T>>来传递嵌套数组[[T]]的内容时,我会写这样的东西。 (Assuming T is a primitive type.) (假设T原始类型。)

let bufPtrArray = someArray.map {subArray -> UnsafeMutableBufferPointer<T> in
    let bufPtr = UnsafeMutableBufferPointer<T>.allocate(capacity: subArray.count)
    _ = bufPtr.initialize(from: subArray)
    return bufPtr
}
defer {bufPtrArray.forEach{bufPtr in bufPtr.deallocate()}}

let addressArray = bufPtrArray.map {bufPtr in UnsafePointer(bufPtr.baseAddress!)}

addressArray.withUnsafeBufferPointer { bufferPointer in
    someCFunction(bufferPointer.baseAddress!)
    //...
}

Or, if you do not need codes specified in //... , you can just write:或者,如果您不需要在//...指定的代码,您可以只写:

someCFunction(addressArray)

The problem for me is that all the premises of the question seem false.我的问题是问题的所有前提似乎都是错误的。 Swift won't copy anything it doesn't have to, so there isn't necessarily any inefficiency in passing actual values. Swift 不会复制任何它不需要的东西,所以在传递实际值时不一定会效率低下。 You can pass a Swift array where a C array is expected.可以在需要 C 数组的地方传递一个 Swift 数组。 And there isn't really any such thing as a multidimensional C array, so you can just pass a one-dimensional array (suitably arranged, of course).并没有真正的多维 C 数组这样的东西,所以你可以只传递一个一维数组(当然,适当排列)。

For example, here's a method that takes an array of int along with information about how big a "row" ( r ) and a "column" ( c ) is to be (code taken from https://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ ):例如,这里有一个方法,它接受一个int数组以及有关“行”( r )和“列”( c )有多大的信息(代码取自https://www.geeksforgeeks.org/动态分配 2d-array-c/ ):

- (void) giveMeACArray: (int*) array r: (int) r c: (int) c {
    int i, j, count;
    int *arr[r];
    for (i=0; i<r; i++)
        arr[i] = (int *)malloc(c * sizeof(int));
    count = 0;
    for (i = 0; i <  r; i++)
        for (j = 0; j < c; j++)
            arr[i][j] = ++count;
    // let's test it
    for (i = 0; i <  r; i++)
        for (j = 0; j < c; j++)
            printf("%d ", arr[i][j]);
}

Let's say that's part of the implementation of an Objective-C class called Thing.假设这是名为 Thing 的 Objective-C 类实现的一部分。 Okay then, here we are in Swift:好的,现在我们在 Swift 中:

let t = Thing()
var arr : [CInt] = [1,2,3,4,5,6,7,8,9,10,11,12]
t.giveMeACArray(&arr, r: 3, c: 4)

Nothing got copied and the right answer got printed.没有被复制,正确的答案被打印出来。 So I don't see what your buffer pointers are for.所以我看不出你的缓冲区指针是干什么用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法转换“UnsafePointer”类型的值<T> &#39; 到预期的参数类型 &#39;UnsafePointer<Int16> &#39; - Cannot convert value of type 'UnsafePointer<T>' to expected argument type 'UnsafePointer<Int16>' 如何在Swift中正确初始化UnsafePointer? - How to correctly initialize an UnsafePointer in Swift? 如何转换UnsafePointer <CUnsignedChar> 串? - How to convert UnsafePointer<CUnsignedChar> to String? 如何在Swift中访问UnsafePointer引用的结构的成员字段的UnsafePointer? - How do I access UnsafePointer of member field of a struct referenced by an UnsafePointer in Swift? 如何将我的swift类转换为与objective-c中的__bridge类似的UnsafePointer - How do I convert my swift class to an UnsafePointer like the __bridge in objective-c 如何将swift数组作为UnsafePointer传递 <T> 函数中的参数 - how to pass a swift Array as UnsafePointer<T> argument in a function 如何更新Swift 3 UnsafePointer的数据语句? - How do I update a statement of Data of UnsafePointer for Swift 3? 如何从Swift中的void UnsafePointer中提取数据? - how do I extract data from void UnsafePointer in Swift? 如何将字符串转换为 UnsafePointer<UInt8> 和长度 - How to convert String to UnsafePointer<UInt8> and length 在不同的UnsafePointer之间进行转换 <T> 在迅速 - Casting between different UnsafePointer<T> in swift
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM