Wey*_* Ng 6 c macos ios swift3 xcode8
我正在尝试将一个lua桥从Swift 2转换为Swift 3.我不是原作者,因此我不太了解库的各个方面,原作者似乎对继续处理该项目不感兴趣.我完成了大部分的转换,但仍有一个地方我被困住了,无法弄明白.我试过在SO和互联网上搜索,但找不到任何可以帮我解决问题的东西.
如果有人有兴趣查看完整的源代码,这里是我在github上的项目分支:https://github.com/weyhan/lua4swift(我的更改是在Swift3分支中)
请允许我设置上下文中我遇到的错误.有一个Userdata类,特别是在方法中userdataPointer<T>() -> UnsafeMutablePointer<T>,c函数lua_touserdata返回userdata的块地址作为void *指针类型.
用Swift 2编写的原始代码:
public class Userdata: StoredValue {
public func userdataPointer<T>() -> UnsafeMutablePointer<T> {
push(vm)
let ptr = lua_touserdata(vm.vm, -1)
vm.pop()
return UnsafeMutablePointer<T>(ptr)
}
public func toCustomType<T: CustomTypeInstance>() -> T {
return userdataPointer().memory
}
public func toAny() -> Any {
return userdataPointer().memory
}
override public func kind() -> Kind { return .Userdata }
}
Run Code Online (Sandbox Code Playgroud)
在使用Xcode 8迁移工具进行转换后,Xcode抱怨返回行有错误Cannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)':
return UnsafeMutablePointer<T>(ptr)
Run Code Online (Sandbox Code Playgroud)
我修好了:
return (ptr?.assumingMemoryBound(to: T.self))!
Run Code Online (Sandbox Code Playgroud)
在上面的更改之后,现在Xcode 8正在抱怨调用语句createCustomType:
public func createCustomType<T: CustomTypeInstance>(setup: (CustomType<T>) -> Void) -> CustomType<T> {
lua_createtable(vm, 0, 0)
let lib = CustomType<T>(self)
pop()
setup(lib)
registry[T.luaTypeName()] = lib
lib.becomeMetatableFor(lib)
lib["__index"] = lib
lib["__name"] = T.luaTypeName()
let gc = lib.gc
lib["__gc"] = createFunction([CustomType<T>.arg]) { args in
let ud = args.userdata
// ******* Here's the line that is causing problem in Swift 3
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
// *******
let o: T = ud.toCustomType()
gc?(o)
return .Nothing
}
if let eq = lib.eq {
lib["__eq"] = createFunction([CustomType<T>.arg, CustomType<T>.arg]) { args in
let a: T = args.customType()
let b: T = args.customType()
return .Value(eq(a, b))
}
}
return lib
}
Run Code Online (Sandbox Code Playgroud)
我遇到困难的地方是:
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
Run Code Online (Sandbox Code Playgroud)
我相信原作者试图清除userdataPointer()调用返回的指针指向的内存块.
使用Xcode 8自动迁移工具,上面的行转换如下:
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
Run Code Online (Sandbox Code Playgroud)
然而Xcode现在抱怨了Cannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer'.
从我的研究来看,对返回线的改变userdataPointer似乎是正确的,所以我认为问题在于对非安全可变的RawPointer进行转换.我已经尝试将强制转换为直接UnsafeMutableRawPointer调用ud.userdataPointer().deinitialize()但是我得到了这个错误Generic parameter 'T' could not be inferred.
我尝试过的其他方法是将UnsafeMutablePointer转换为UnsafeMutableRawPointer但它总是导致Xcode 8抱怨一件事或另一件事.有关如何使其工作的任何建议?
您可能已经发现,Swift 3 尝试在指针方面提供更好的类型安全性。 UnsafeMutablePointer现在只能表示指向已知类型实例的指针。在 Swift 2 中,Cvoid *由 表示UnsafeMutablePointer<Void>,允许以相同的方式处理 void 和非 void 指针,包括尝试调用指向类型的反初始化器,这就是有destroy()问题的行中的方法代码的作用是:
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
Run Code Online (Sandbox Code Playgroud)
在 Swift 3 中,指针对象上的反初始化器是使用结构体deinitialize()的方法调用的UnsafeMutablePointer。看来迁移助理很困惑。线路
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
Run Code Online (Sandbox Code Playgroud)
没有什么意义,因为 (1)UnsafeMutablePointer不能使用asto进行转换UnsafeMutableRawPointer;(2)UnsafeMutableRawPointer没有deinitialize()方法。在 Swift 3 中,UnsafeMutableRawPointer是表示 的特殊类型void*。迁移工具犯这个错误的原因其实是可以理解的:它盲目地用 和 替换了destroy()相应deinitialize()的UnsafeMutablePointer<Void>Swift 3 type UnsafeMutableRawPointer,而没有意识到转换不起作用。
我不太明白为什么调用destroy()void 指针可以在 Swift 2 中工作。也许这是程序中的一个错误,或者某些编译器技巧允许调用正确的反初始化程序。在对代码不够了解的情况下,我不能更具体地建议分析它以找出被destroy()调用的指针所指向的类型。例如,如果我们确定它始终是T以下行中使用的占位符类型:
let o: T = ud.toCustomType()
Run Code Online (Sandbox Code Playgroud)
那么有问题的行就变成了
(ud.userdataPointer() as UnsafeMutablePointer<T>).deinitialize()
Run Code Online (Sandbox Code Playgroud)
我们需要括号中的转换以允许编译器推断泛型参数。
感谢您提出一个有趣的问题。顺便说一句,一旦克服了这个障碍,你很可能会遇到其他问题。值得注意的一件事是Swift 3 中UnsafeMutablePointer没有这一点;.memory你必须使用.pointee它。
这是一个更新。在 Linux 上使用 Swift 2.2 后,我意识到调用强制类型destroy()转换UnsafeMutablePointer<A>asUnsafeMutablePointer<Void>不会调用 A 的析构器,即使它有一个。所以,你必须小心这条线......
| 归档时间: |
|
| 查看次数: |
602 次 |
| 最近记录: |