我正在编写一个Swift应用程序,我需要使用C函数从套接字进行一些网络缓冲。Swift通过桥接头导入这些函数,它们需要一个缓冲区指针参数。
这两个函数有效地:
read(Socket s, void *buf, int num);
write(Socket s, const void *buf, int num);
Swift编译器指出,如果这些函数需要一个UnsafePointer<Void>
。我有一些[UInt8]
类型保存我的可写数据和接受我的可读数据。Swift编译器并没有抱怨我所写的东西,但是我相信下面的代码并没有按照我在C语法中期望的那样做。
这是我的read循环:
var index: Int32 = 0
while index < length {
var toRead = length - index
if toRead > bufferSize {
toRead = bufferSize
}
// Read into my buffer ([Int8]), starting at element `hasRead`
let justRead: Int32 = read(s, &buffer[Int(index)], toRead)
index += justRead
}
和我的write循环:
var index: Int32 = 0
while index < length {
var toWrite: Int32 = length - index
if toWrite > bufferSize {
toWrite = bufferSize
}
// Write from my buffer ([Int8]), starting at element `index`
let wrote = write(s, &buffer[Int(index)], toWrite)
index += wrote
}
我的问题是:在这种情况下,&buffer[Int(index)]
是传递(可变)数组的正确方法吗?(也就是说,它正在做我期望C用这种语法做的事情-获取数组字节的第索引元素的地址)。如果不是,我如何恰当地将[UInt8]
传递给桥接的C函数?
我建议谨慎使用&buffer[Int(index)]
。目前还不清楚从医生那里能保证什么。当然,它可以用来修改数组的单个元素,但我认为你不应该依赖于指针运算(所以你不应该把它传递给这样的函数)。
withUnsafeMutableBufferPointer()
(目前显然不在文档中)(或不可变版本)。这保证使用一个UnsafeMutableBufferPointer来调用所提供的闭包,该闭包指向可用于读取和写入数组的连续存储。您可能会想使用它的baseAddress
.
(还要注意Swift除了Array之外还有一个连续数组,它的存储保证是连续的,所以你可能会看到比Array更好的性能,因为你知道你无论如何都会要求它提供一个连续的缓冲区。)但是不要在这里对性能做太多的假设——它没有很好的文档记录!我怀疑你需要在实践中使用连续数组
你可以:
read(s, &buffer + Int(index), toRead)
我认为,&buffer[Int(index)]
是不安全的,正如在这个QA