Dear community --
As personal side project and to understand how it works, I'm currently working on a serial library written in Swift.
I've thoroughly studied the code written in both yeokm1/SwiftSerial and armadsen/ORSSerialPort (in Obj-C as well as the uncompleted Swift rewrite in branch 3.0)
After spending several days neck deep in documentation trying to understand the ins & outs of termios
& co., things are getting clearer and it's actually pretty simple to understand and use once you get your head around it (even though Swift is not really helping with control characters
, C-functions and tuples...).
Now that I can setup and open a port, my next goal (obviously) is to write to it.
Foundation provides us with a nice wrapper around the C-function write
:
// C function
ssize_t write(int fd, const void *buf, size_t count);
// Swift
func write(_ __fd: Int32, _ __buf: UnsafeRawPointer!, _ __nbyte: Int) -> Int
Now I would like to be able to write only one byte with the write(byte:UInt8)
function. This was my first attempt:
func write(byte: UInt8) Int {
let bytesWritten = Darwin.write(fd, byte, 1)
return bytesWritten
}
Obviously this does not work as I'm not passing an UnsafeRawPointer
to write
.
The other libraries will usually take the Data/NSData
path to achieve the result. For example in SwiftSerial:
func writeData(_ data: Data) throws -> Int {
let size = data.count
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
defer {
buffer.deallocate(capacity: size)
}
data.copyBytes(to: buffer, count: size)
let bytesWritten = Darwin.write(fd, buffer, size)
return bytesWritten
}
But I find this allocate/deallocate thing cumbersome and overly complex... After some experimentation, I managed to fix my write
function by simply doing this:
func write(byte: UInt8) Int {
let buffer: [UInt8] = [byte]
let bytesWritten = Darwin.write(fd, buffer, 1)
return bytesWritten
}
And if I want to write an array of bytes, I can just do this:
func write(array: [UInt8]) Int {
let size = array.count
let bytesWritten = Darwin.write(fd, array, size)
return bytesWritten
}
Now I have 4 questions:
- Am I doing something wrong? Or is using
[UInt8]
perfectly valid? - Am I losing some optimization/speed compared to the whole
UnsafeMutablePointer.allocate/deallocate
thing? - Is
Array
just a clever way of hiding the complexity ofUnsafeMutablePointer
? - Would
Data/NSData
bring useful features I might need in the future?
Thanks a lot!
-- Ladislas
-- Edit --
I changed my write(byte:)
function to the following, which seems to be better.
func write(byte: UInt8) Int {
var buffer = byte
let bytesWritten = Darwin.write(fd, &buffer, 1)
return bytesWritten
}