POSIX def test(path, gradient_magnitude=1.):
im = Image.open(path)
if im.mode != 'RGBA':
im = im.convert('RGBA')
width, height = im.size
gradient = Image.new('L', (width, 1), color=0xFF)
for x in range(width):
# gradient.putpixel((x, 0), 255-x)
gradient.putpixel((x, 0), int(255 * (1 - gradient_magnitude * float(x)/width)))
alpha = gradient.resize(im.size)
black_im = Image.new('RGBA', (width, height), color=0) # i.e. black
black_im.putalpha(alpha)
gradient_im = Image.alpha_composite(im, black_im)
gradient_im.save('out.png', 'PNG')
分配以后必须使用getaddrinfo
释放的内存。
见http://manpages.ubuntu.com/manpages/xenial/en/man3/getaddrinfo.3.html
为了简化API,我创建了这个功能:
freeaddrinfo
但是,我并不觉得这个功能是正确的。
import Foundation
enum SystemError: Swift.Error {
case getaddrinfo(Int32, Int32?)
}
public func getaddrinfo(node: String?, service: String?, hints: addrinfo?) throws -> [addrinfo] {
var err: Int32
var res: UnsafeMutablePointer<addrinfo>?
if var hints = hints {
err = getaddrinfo(node, service, &hints, &res)
} else {
err = getaddrinfo(node, service, nil, &res)
}
if err == EAI_SYSTEM {
throw SystemError.getaddrinfo(err, errno)
}
if err != 0 {
throw SystemError.getaddrinfo(err, nil)
}
defer {
freeaddrinfo(res)
}
var result = [addrinfo]()
var ai = res?.pointee
while ai != nil {
result.append(ai!)
ai = ai!.ai_next?.pointee
}
return result
}
分配内存,Swift不应该用自己的东西覆盖那个内存?getaddrinfo
删除整个列表,并且它应该复制已分配给结果数组的ai信息?与freeaddrinfo
接口的正确方法是什么?
答案 0 :(得分:3)
getaddrinfo
分配的内存(例如malloc
)将不会被授予任何其他内存
动态内存分配功能在同一个运行过程中
直到freeaddrinfo
发布(例如free
)。
因此,Swift运行时不会践踏该内存(如果我们这样做)
假设它没有编程错误,例如错误的指针计算。)
同样struct addrinfo
是值类型,所以
result.append(ai!)
会将指向结构的副本附加到数组中。
但仍有问题。 struct addrinfo
的部分成员
是指针
public var ai_canonname: UnsafeMutablePointer<Int8>! /* canonical name for hostname */
public var ai_addr: UnsafeMutablePointer<sockaddr>! /* binary address */
可能指向由getaddrinfo
分配的内存,因此
在freeaddrinfo
之后无效,并在您之后取消引用它们
函数返回导致未定义的行为。
因此,你必须推迟freeaddrinfo
直到。{
不再需要地址列表,或复制信息。
这有点麻烦,因为ai_addr
可能指向a
IPv4或IPv6套接字地址结构,长度不同。
以下代码演示了如何复制地址列表
到一个sockaddr_storage
结构数组(足够大)
持有任何IP地址)。此代码尚未经过全面测试,
所以要小心使用它。
public func getaddrinfo(node: String, service: String, hints: addrinfo?) throws -> [sockaddr_storage] {
var err: Int32
var res: UnsafeMutablePointer<addrinfo>?
if var hints = hints {
err = getaddrinfo(node, service, &hints, &res)
} else {
err = getaddrinfo(node, service, nil, &res)
}
if err == EAI_SYSTEM {
throw SystemError.getaddrinfo(err, errno)
}
if err != 0 {
throw SystemError.getaddrinfo(err, nil)
}
defer {
freeaddrinfo(res)
}
guard let firstAddr = res else {
return []
}
var result = [sockaddr_storage]()
for addr in sequence(first: firstAddr, next: { $0.pointee.ai_next }) {
var sockAddr = sockaddr_storage()
memcpy(&sockAddr, addr.pointee.ai_addr, Int(addr.pointee.ai_addrlen))
result.append(sockAddr)
}
return result
}
说明:
如果您只对单个地址系列感兴趣,那么
您可以sockaddr_storage
或sockaddr_in
替换sockaddr_in6
node
。
我已将service
和sequence()
参数设为非可选参数。
原因是Swift在传递更多时目前有一个Bug
比C函数的一个可选字符串,请参阅
Why does Swift return an unexpected pointer when converting an optional String into an UnsafePointer?
while
来遍历链表,而不是
一个thingHolder.innerHTML += html
循环。