unsafe-swift | C experiments in Swift | iOS library
kandi X-RAY | unsafe-swift Summary
kandi X-RAY | unsafe-swift Summary
C experiments in Swift =.
Support
Quality
Security
License
Reuse
Top functions reviewed by kandi - BETA
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample of unsafe-swift
unsafe-swift Key Features
unsafe-swift Examples and Code Snippets
Community Discussions
Trending Discussions on unsafe-swift
QUESTION
I've been working quite a bit with Apple's neural net tools, which means I've been working quite a bit with unsafe pointers. I grew up with C, and I've been working with Swift for quite a while, so I'm comfortable using them, but there's one thing about them that has me totally stumped.
I can't figure out why there's any effort involved in deriving one kind of unsafe pointer from another. In general, it seems like it should be trivial, but the initializers for the different types are specific about what kind of input they'll take, and I'm having a hard time figuring out the rules.
An easy and specific example, perhaps the one that stumps me the most
...ANSWER
Answered 2021-Mar-03 at 03:07The distinction between these types isn't quite as large as you might imagine. Conceptually, UnsafeBufferPointer
can be viewed as a tuple of (UnsafePointer, Int)
, i.e., a pointer to a buffer of elements in memory with a known count. UnsafePointer
, in contrast, is a pointer to an element in memory with an unknown count; UnsafePointer
more closely represents what you might be used to as an arbitrary pointer in C: it may point to a single element, or to the start of a contiguous grouping of several elements, but on its own, there's no way to find out.
UnsafeBufferPointer
having a known count also means that it is able to conform to Collection
(which requires a known start and end) as opposed to UnsafePointer
, which doesn't have that information.
Swift is very much a language of semantics, and places great emphasis on expressing in the type system knowledge about the tools you have available to you. As you point out, there are operations you can perform on one type and not another — this is by design, to make some operations more difficult to perform incorrectly.
These pointers are convertible, too:
UnsafeBufferPointer
has abaseAddress
which is anUnsafePointer
: given a buffer, you can always "throw away" information about the count to get the underlying uncounted pointer- Given an
UnsafePointer
and acount
, you can also express the existence of a buffer in memory withUnsafeBufferPointer.init(start:count:)
The general answer is: use the most specific pointer type that you can to represent the data that you have. It is usually preferred to that you use the Buffer
variants of pointers if you're pointing to more than one element, and know how many you have. Similarly, if you're pointing to arbitrary bytes in memory (which may or may not have a type), you should use Raw
pointers if possible. (And, of course, if you need to write to these locations in memory, you'll need to use the Mutable
variants of those too.)
For more information, I highly recommend Andrew Trick's talk from WWDC 2020 about this subject: Safely manage pointers in Swift. He goes into great detail about the conceptual state machine representing the lifetimes of pointers in Swift, and how to convert between and use the pointer types correctly. (It's as close to the horse's mouth as you can get when on the topic.)
Separately, about your example code: @Sweeper correctly points out in a comment that if you're looking to allocate a buffer of Float
s, you shouldn't allocate a raw buffer and bind its memory type. In general, allocating raw buffers not only runs the risk of mistaking the size of the buffer needed, but also risks not taking into account padding (which would have to be calculated manually for some types).
Instead, you should use UnsafeMutableBufferPointer.allocate(capacity:)
to allocate the buffer, which you can then write to. It correctly takes into account alignment and padding, so you can't get it wrong.
The difference between raw memory and typed memory is very subtle in Swift, and Andy describes it much better in the linked talk than I can here, but tl;dr: raw memory is a collection of untyped bytes which could represent anything, whereas typed memory represents only values of a specific type (and cannot be safely reinterpreted arbitrarly, save for a few exceptions, a major departure from C!); you should almost never have to bind memory manually, and if you bind memory to non-trivial types, you're almost certainly doing it wrong. (Not that you're doing that here, but just a heads-up)
Finally, on the subject of Strideable
vs. Collection
, and subscripting — the fact that you can subscript into both matches the behavior of C, but has a subtle semantic distinction in Swift.
Subscripting into an UnsafePointer
means largely what it does in C: an UnsafePointer
knows its base type, and referencing a single location in memory, can calculate where the next object of that type in memory would be using the type's alignment and padding (this is what its Strideable
conformance implies); subscripting allows you to access one of several contiguous objects in memory relative to the one the pointer refers to. Also, just like in C: because you don't know where a group of such objects ends, you can subscript arbitrarily using an UnsafePointer
with no bounds checks — there simply wouldn't be any way to know whether an access you're trying to make is valid ahead of time.
On the other hand, subscripting through UnsafeBufferPointer
is like accessing an element inside of a collection of elements in memory. Because there are clear bounds on where the buffer starts and ends, you get bounds checking, and indexing out of bounds on an UnsafeBufferPointer
is much more clearly an error. Along those lines, a Strideable
conformance on UnsafeBufferPointer
wouldn't make much sense: the "stride" of a Strideable
type indicates that it knows how to get to the "next" one, but there isn't a logical "next" buffer after an entire UnsafeBufferPointer
.
So both of these types end up with a subscript operator that effectively performs the same operation, but semantically has a very different meaning.
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install unsafe-swift
Support
Reuse Trending Solutions
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesStay Updated
Subscribe to our newsletter for trending solutions and developer bootcamps
Share this Page