I am trying to convert this into swift.
Facing issue at memory allocation logic
Byte *p[10000];
p[allocatedMB] = malloc(1048576);
memset(p[allocatedMB], 0, 1048576);
How to write this in swift?
You can use malloc from Swift, it returns a "raw pointer":
var p: [UnsafeMutableRawPointer?] = Array(repeating: nil, count: 10000)
var allocatedMB = 0
p[allocatedMB] = malloc(1048576)
memset(p[allocatedMB], 0, 1048576)
Alternatively, use UnsafeMutablePointer and its
allocate and initialize methods:
var p: [UnsafeMutablePointer<UInt8>?] = Array(repeating: nil, count: 10000)
var allocatedMB = 0
p[allocatedMB] = UnsafeMutablePointer.allocate(capacity: 1048576)
p[allocatedMB]?.initialize(to: 0, count: 1048576)
Related
I'm getting the error below for this statement:
let data = Data(bytes: UnsafePointer<UInt8>(cubeData), count: cubeData.count * MemoryLayout<Float>.size)
cubeData is defined as: var cubeData = [Float](repeating: 0, count: size * size * size * 4)
Error:
'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.
How can I fix this?
Thanks!
You could use Array.withUnsafeBufferPointer to obtain a buffer pointer (i.e. a pointer to an array with its length). Then use Data.init(buffer:) to initiate the data from a buffer pointer.
let cubeData: [Float] = [1.1, 2.2, 3.3, 4.4]
let b = cubeData.withUnsafeBufferPointer { Data(buffer: $0) }
print(b as NSData)
// <cdcc8c3f cdcc0c40 33335340 cdcc8c40>
Is it possible to create a [UInt8] from an UnsafeMutablePointer<UInt8> without copying the bytes?
In the NSData world I could simply call
let data = NSData(bytesNoCopy: p, length: n, freeWhenDone: false)
and just wrap the pointer.
As already mentioned in the comments, you can create an
UnsafeMutableBufferPointer from the pointer:
let a = UnsafeMutableBufferPointer(start: p, count: n)
This does not copy the data, which means that you have to ensure that
the pointed-to data is valid as long as a is used.
Unsafe (mutable) buffer pointers have similar access methods like arrays,
such as subscripting:
for i in 0 ..< a.count {
print(a[i])
}
or enumeration:
for elem in a {
print(elem)
}
You can create a "real" array from the buffer pointer with
let b = Array(a)
but this will copy the data.
Here is a complete example demonstrating the above statements:
func test(_ p : UnsafeMutablePointer<UInt8>, _ n : Int) {
// Mutable buffer pointer from data:
let a = UnsafeMutableBufferPointer(start: p, count: n)
// Array from mutable buffer pointer
let b = Array(a)
// Modify the given data:
p[2] = 17
// Printing elements of a shows the modified data: 1, 2, 17, 4
for elem in a {
print(elem)
}
// Printing b shows the orignal (copied) data: 1, 2, 3, 4
print(b)
}
var bytes : [UInt8] = [ 1, 2, 3, 4 ]
test(&bytes, bytes.count)
You can use UnsafeBufferPointer + map to achieve your goal.
KEEP IN MIND: pointer boundary should be maintained by yourself, while arrays will do by itself
let bytesArray = UnsafeBufferPointer(start: bts, count: bytes.count).map{$0}
Swift 5, Xcode 11:
var bytes: [UInt8] = [1, 3, 5, 7]
let count = bytes.count
print(bytes)
// MARK: - [UInt8] -> UnsafePointer<UInt8>
// producing dangling pointer warning bug?
let bts1: UnsafePointer<UInt8> = UnsafePointer(bytes)
print(bts1, bts1[0], bts1[1], bts1[2], bts1[3], bts1[4])
let bts = withUnsafePointer(to: &bytes[0]) {
$0.withMemoryRebound(to: UInt8.self, capacity: count) { $0 }
}
print(bts, bts[0], bts[1], bts[4])
// MARK: - UnsafePointer<UInt8> -> [UInt8]
let bytesArray = UnsafeBufferPointer(start: bts, count: bytes.count).map{$0}
print(bytesArray, bytesArray[0], bytesArray[1]/*, bytesArray[4]*/)
output:
[1, 3, 5, 7]
0x0000600001946840 1 3 5 7 0
0x0000600001946840 1 3 0
[1, 3, 5, 7] 1 3
bad samples:
/// invalid sample 1
let testA = withUnsafePointer(to: &bytes) {
$0.withMemoryRebound(to: UInt8.self, capacity: count) { $0 }
}
print(testA, testA[0], testA[1], testA[4])
/// invalid sample 2
let testB = withUnsafePointer(to: bytes[0]) {
$0.withMemoryRebound(to: UInt8.self, capacity: count) { $0 }
}
print(testB, testB[0], testB[1], testB[4])
output:
0x0000000102b4f520 32 104 0
0x00007ffeed203ac0 192 58 254
I have this output from NSData: <00000100 84000c00 071490fe 4dfbd7e9>
So how could I byte reverse it in Swift and have this output: <00000001 0084000c 1407fe90 fb4de9d7>?
This should work to swap each pair of adjacent bytes in the data.
The idea is to interpret the bytes as an array of UInt16 integers
and use the built-in byteSwapped property.
func swapUInt16Data(data : NSData) -> NSData {
// Copy data into UInt16 array:
let count = data.length / sizeof(UInt16)
var array = [UInt16](count: count, repeatedValue: 0)
data.getBytes(&array, length: count * sizeof(UInt16))
// Swap each integer:
for i in 0 ..< count {
array[i] = array[i].byteSwapped // *** (see below)
}
// Create NSData from array:
return NSData(bytes: &array, length: count * sizeof(UInt16))
}
If your actual intention is to convert data from an (external)
big-endian representation to the host (native) byte order (which happens to be little-endian on all current iOS and OS X devices) then you should replace *** by
array[i] = UInt16(bigEndian: array[i])
Example:
var bytes : [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8]
let data = NSData(bytes: &bytes, length: bytes.count)
print(data)
// <01020304 05060708>
print(swapUInt16Data(data))
// <02010403 06050807>
Update for Swift 3: The generic withUnsafeMutableBytes()
methods allows to obtain a UnsafeMutablePointer<UInt16> to the bytes
and modify them directly:
func swapUInt16Data(data : Data) -> Data {
var mdata = data // make a mutable copy
let count = data.count / MemoryLayout<UInt16>.size
mdata.withUnsafeMutableBytes { (i16ptr: UnsafeMutablePointer<UInt16>) in
for i in 0..<count {
i16ptr[i] = i16ptr[i].byteSwapped
}
}
return mdata
}
Example:
let data = Data(bytes: [1, 2, 3, 4, 5, 6, 7, 8])
print(data as NSData) // <01020304 05060708>
let swapped = swapUInt16Data(data: data)
print(swapped as NSData) // <02010403 06050807>
CoreFoundation has CFSwapInt32BigToHost and CFSwapInt32LittleToHost and other swap functions.
In swift3 it looks like this
struct FileHeader {
var magicNumber: UInt32 = 0
var count: UInt32 = 0
var width: UInt32 = 0
var height: UInt32 = 0
static func create(data: Data) -> FileHeader {
let structSize = MemoryLayout<FileHeader>.size
assert(data.count >= structSize)
var result = FileHeader()
let nsdata = data as NSData
nsdata.getBytes(&result, range: NSRange(location: 0, length: structSize))
result.magicNumber = CFSwapInt32BigToHost(result.magicNumber)
result.count = CFSwapInt32BigToHost(result.count)
result.width = CFSwapInt32BigToHost(result.width)
result.height = CFSwapInt32BigToHost(result.height)
return result
}
}
For someone may want to restrict the byte pattern, it would be a solution:
func swap<U:IntegerType>(data:NSData,_ :U.Type) -> NSData{
var length = data.length / sizeof(U)
var bytes = [U](count: length, repeatedValue: 0)
data.getBytes(&bytes, length: data.length)
// since byteSwapped isn't declare in any protocol, so we have do it by ourselves manually.
var inverse = bytes.enumerate().reduce([U](count: length, repeatedValue: 0)) { (var pre, ele) -> [U] in
pre[length - 1 - ele.index] = ele.element
return pre
}
return NSData(bytes: inverse, length: data.length)
}
for example:
swap(data:data,UInt8.self)
//before <0c20207b 17>
//after <177b2020 0c>
swap(data:anotherData,UInt16.self)
//before <8e004c01 84008f05 0701>
//after <07018f05 84004c01 8e00>
I'm trying to do some network code in swift and the type checking is giving me fits.
var sock: CInt = ...
var rin: sockaddr_in
var rlen = socklen_t(sizeof(sockaddr_in))
var buffer: CChar[] = CChar[](count: 128, repeatedValue: 0)
let len = recvfrom(sock, &buffer, 128, 0, &rin, &rlen)
The compiler complains (very cryptically) at the recvfrom about the fact that &rin is a pointer to sockaddr_in instead of sockaddr. I tried various ways to convert the pointer type, but I can't seem to get this right.
If I declare it to be a sockaddr I can get this to compile, but then I can't look at it as a sockaddr_in.
Update for Swift 3 and later, compare UnsafeRawPointer Migration:
var sock: CInt = 1234
var rin = sockaddr_in()
var rlen = socklen_t(MemoryLayout.size(ofValue: rin))
var buffer = [CChar](repeating: 0, count: 128)
let len = withUnsafeMutablePointer(to: &rin) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
recvfrom(sock, &buffer, buffer.count, 0, $0, &rlen)
}
}
Update: As of Swift 1.2 (Xcode 6.3 beta), initializing a C struct
has become much simpler:
var rin = sockaddr_in()
defines a sockaddr_in variable and initializes all elements to zero.
The conversion of a address of sockaddr_in to an an address of
sockaddr is done as follows:
let len = withUnsafeMutablePointer(&rin) {
recvfrom(sock, &buffer, UInt(buffer.count), 0, UnsafeMutablePointer($0), &rlen)
}
Old answer: The first problem is that the sockaddr_in variable has to be initialized before
its address can be passed to recvfrom(). Initializing complex structs in Swift
seems to be clumsy, compare
Swift: Pass Uninitialized C Structure to Imported C function.
Using the helper function from
https://stackoverflow.com/a/24335355/1187415:
func initStruct<S>() -> S {
let struct_pointer = UnsafeMutablePointer<S>.alloc(1)
let struct_memory = struct_pointer.move()
struct_pointer.dealloc(1)
return struct_memory
}
the socket address can be initialized as
var rin : sockaddr_in = initStruct()
To cast the sockaddr_in pointer to a sockaddr pointer, use reinterpretCast().
let len = recvfrom(sock, &buffer, UInt(buffer.count), 0, reinterpretCast(&rin), &rlen)
If I assign a float array to a CMutablePointer<Float> in a Swift playground as follows, I get a runtime crash:
var floatArray:Float[] = Array(count: 3, repeatedValue: 2.5)
var floatPointer:CMutablePointer<Float> = &floatArray
Is my code incorrect (if so how?), or should I file this as a bug with Apple?
Your param is a tab so you have to do like this
var floatArray:Float[] = Array(count: 3, repeatedValue: 2.5)
var floatPointer:CMutablePointer<Float[]> = &floatArray
Your code, when compiled and run outside of the Playground:
var floatArray:Float[] = Array(count: 3, repeatedValue: 2.5)
var floatPointer:CMutablePointer<Float> = &floatArray
floatPointer.withUnsafePointer { (myPtr1 : UnsafePointer<Float>) -> () in
var x = myPtr1.memory
println("float array element 0 is \(x)")
}
prints 2.5