Swift2 @convention(c) 带有 char* 和 type**
Swift2 @convention(c) with char* and type**
我正在尝试编写指向 c 方法的指针:
//c signature:
typedef void (*startDocumentSAXFunc) (void *ctx);
//Swift2 working code
let startDocument: @convention(c) (UnsafeMutablePointer<Void>) -> Void = { (ctx) -> Void in
NSLog("Start Document")
}
- 我找不到要用于 xmlChar**
的类型
//c signature
typedef void (*startElementSAXFunc) (void *ctx,
const xmlChar *name,
const xmlChar **atts);
//Swift2 code
let startElement: @convention(c) (UnsafeMutablePointer, UnsafePointer, ???) -> Void = { (ctx, name, attributes) -> Void in
NSLog("Start Element \(name), \(attributes)")
}
- 我找不到要用于 const char*
的类型
//c signature
typedef void (XMLCDECL *errorSAXFunc) (void *ctx,
const char *msg, ...);
//Swift2
let error: @convention(c) (UnsafeMutablePointer, ???) -> Void =
{ (ctx, msg) -> Void in
NSLog("Error \(msg)")
}
我尝试了类型 UnsafePointer 但它不起作用。
这里的目的是能够使用比 NSXML 库更快的 libXML。
感谢您的帮助!
检查此 'self explanatory' 示例
let str = "A"
var c = str.utf8.map { (c) -> CChar in
return CChar(c)
}[0]
print(c, c.dynamicType) // 65 Int8
var p = UnsafeMutablePointer<CChar>.alloc(1)
print(p.memory, p.memory.dynamicType) // 0 Int8
p.memory = 65
func modify(pp: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>)->Void {
print(pp.memory.memory, pp.memory.memory.dynamicType)
}
let pp = withUnsafeMutablePointer(&p){ [=10=] }
print(pp, pp.dynamicType) // 0x0000000119bbf750 UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
modify(pp) // 65 Int8
...
p.dealloc(1)
modify(pp) // -107 Int8
// -107 is some 'random' value, becase the memory there was dealocated!!
UnsafePoiner<CChar>
是 const char *
而
UndafeMutablePointer<CChar>
是 char *
等...
C函数类型
void (*startElementSAXFunc) (void *ctx,
const xmlChar *name,
const xmlChar **atts);
映射到 Swift 为
(UnsafeMutablePointer<Void>, UnsafePointer<xmlChar>, UnsafeMutablePointer<UnsafePointer<xmlChar>>) -> Void
所以有效的 startElementSAXFunc
是
func onStartElement(ctx: UnsafeMutablePointer<Void>,
name: UnsafePointer<xmlChar>,
atts: UnsafeMutablePointer<UnsafePointer<xmlChar>>) {
// ...
}
并且可以在没有任何转换的情况下分配给处理程序:
var handler = xmlSAXHandler()
handler.initialized = XML_SAX2_MAGIC
// ...
handler.startElement = onStartElement
现在 xmlChar
是 unsigned char
的类型别名,即 UInt8
在 Swift 中,与 CChar
又名 Int8
不同,因此
如果转换传递的字符,则需要额外的强制转换
到 onStartElement
:
中的 Swift 字符串
let sName = String.fromCString(UnsafePointer(name))!
print("start element, name = ", sName)
atts
是指向字符指针数组的指针,而你
可以像在 C:
中一样遍历该数组
if atts != nil {
var ptr = atts
while ptr[0] != nil && ptr[1] != nil {
let key = String.fromCString(UnsafePointer(ptr[0]))!
let value = String.fromCString(UnsafePointer(ptr[1]))!
print("attr:", key, "=", value)
ptr += 2
}
}
以类似的方式,您可以实现 endElementSAXFunc
和 charactersSAXFunc
.
但是errorSAXFunc
有一个大问题:
该函数使用可变参数列表,因此不能
在 Swift 中实现,所以你在这里运气不好。
以下编译并且似乎到运行:
let onError : @convention(c) (UnsafeMutablePointer<Void>, UnsafePointer<xmlChar>)->Void = {
(ctx, msg) in
let sMsg = String.fromCString(UnsafePointer(msg))!
print("error:", sMsg)
}
handler.error = unsafeBitCast(onError, errorSAXFunc.self)
但据我所知,这是未定义的行为。
这也没有帮助,因为您会得到错误格式字符串
仅(在我的测试用例中只是 %s
)。
我正在尝试编写指向 c 方法的指针:
//c signature:
typedef void (*startDocumentSAXFunc) (void *ctx);
//Swift2 working code
let startDocument: @convention(c) (UnsafeMutablePointer<Void>) -> Void = { (ctx) -> Void in
NSLog("Start Document")
}
- 我找不到要用于 xmlChar** 的类型
//c signature typedef void (*startElementSAXFunc) (void *ctx, const xmlChar *name, const xmlChar **atts); //Swift2 code let startElement: @convention(c) (UnsafeMutablePointer, UnsafePointer, ???) -> Void = { (ctx, name, attributes) -> Void in NSLog("Start Element \(name), \(attributes)") }
- 我找不到要用于 const char* 的类型
//c signature typedef void (XMLCDECL *errorSAXFunc) (void *ctx, const char *msg, ...); //Swift2 let error: @convention(c) (UnsafeMutablePointer, ???) -> Void = { (ctx, msg) -> Void in NSLog("Error \(msg)") }
我尝试了类型 UnsafePointer
这里的目的是能够使用比 NSXML 库更快的 libXML。
感谢您的帮助!
检查此 'self explanatory' 示例
let str = "A"
var c = str.utf8.map { (c) -> CChar in
return CChar(c)
}[0]
print(c, c.dynamicType) // 65 Int8
var p = UnsafeMutablePointer<CChar>.alloc(1)
print(p.memory, p.memory.dynamicType) // 0 Int8
p.memory = 65
func modify(pp: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>)->Void {
print(pp.memory.memory, pp.memory.memory.dynamicType)
}
let pp = withUnsafeMutablePointer(&p){ [=10=] }
print(pp, pp.dynamicType) // 0x0000000119bbf750 UnsafeMutablePointer<UnsafeMutablePointer<Int8>>
modify(pp) // 65 Int8
...
p.dealloc(1)
modify(pp) // -107 Int8
// -107 is some 'random' value, becase the memory there was dealocated!!
UnsafePoiner<CChar>
是 const char *
而
UndafeMutablePointer<CChar>
是 char *
等...
C函数类型
void (*startElementSAXFunc) (void *ctx,
const xmlChar *name,
const xmlChar **atts);
映射到 Swift 为
(UnsafeMutablePointer<Void>, UnsafePointer<xmlChar>, UnsafeMutablePointer<UnsafePointer<xmlChar>>) -> Void
所以有效的 startElementSAXFunc
是
func onStartElement(ctx: UnsafeMutablePointer<Void>,
name: UnsafePointer<xmlChar>,
atts: UnsafeMutablePointer<UnsafePointer<xmlChar>>) {
// ...
}
并且可以在没有任何转换的情况下分配给处理程序:
var handler = xmlSAXHandler()
handler.initialized = XML_SAX2_MAGIC
// ...
handler.startElement = onStartElement
现在 xmlChar
是 unsigned char
的类型别名,即 UInt8
在 Swift 中,与 CChar
又名 Int8
不同,因此
如果转换传递的字符,则需要额外的强制转换
到 onStartElement
:
let sName = String.fromCString(UnsafePointer(name))!
print("start element, name = ", sName)
atts
是指向字符指针数组的指针,而你
可以像在 C:
if atts != nil {
var ptr = atts
while ptr[0] != nil && ptr[1] != nil {
let key = String.fromCString(UnsafePointer(ptr[0]))!
let value = String.fromCString(UnsafePointer(ptr[1]))!
print("attr:", key, "=", value)
ptr += 2
}
}
以类似的方式,您可以实现 endElementSAXFunc
和 charactersSAXFunc
.
但是errorSAXFunc
有一个大问题:
该函数使用可变参数列表,因此不能
在 Swift 中实现,所以你在这里运气不好。
以下编译并且似乎到运行:
let onError : @convention(c) (UnsafeMutablePointer<Void>, UnsafePointer<xmlChar>)->Void = {
(ctx, msg) in
let sMsg = String.fromCString(UnsafePointer(msg))!
print("error:", sMsg)
}
handler.error = unsafeBitCast(onError, errorSAXFunc.self)
但据我所知,这是未定义的行为。
这也没有帮助,因为您会得到错误格式字符串
仅(在我的测试用例中只是 %s
)。