Tôi đang cố chuyển đổi cầu lua từ Swift 2 sang Swift 3. Tôi không phải là tác giả gốc nên có các khía cạnh của thư viện mà tôi không biết rõ và tác giả gốc dường như không quan tâm để tiếp tục làm việc dự án. Tôi có hầu hết các chuyển đổi được thực hiện nhưng vẫn còn một nơi tôi đang mắc kẹt và không thể tìm ra. Tôi đã thử tìm kiếm trên SO và trên Internet nhưng không thể tìm thấy bất cứ điều gì có thể giúp tôi giải quyết vấn đề.Làm thế nào để chuyển đổi 'void *' trở về từ một hàm C thành 'UnsafeMutableRawPointer' trong Swift 3?
Nếu bất cứ ai quan tâm đến việc nhìn vào mã nguồn đầy đủ, đây là ngã ba của tôi về dự án trên github: https://github.com/weyhan/lua4swift (những thay đổi của tôi là tại các chi nhánh Swift3)
Cho phép tôi thiết lập bối cảnh đến lỗi tôi m bị kẹt trên. Có một lớp Userdata, cụ thể trong phương thức userdataPointer<T>() -> UnsafeMutablePointer<T>
hàm c lua_touserdata
trả về địa chỉ khối của userdata dưới dạng kiểu con trỏ void *
.
đang gốc viết bằng 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 }
}
Sau khi chuyển đổi với công cụ di cư Xcode 8, Xcode được phàn nàn về dòng trở lại với lỗi Cannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)'
:
return UnsafeMutablePointer<T>(ptr)
Tôi đã khắc phục nó với:
return (ptr?.assumingMemoryBound(to: T.self))!
Sau thay đổi ở trên, bây giờ Xcode 8 hiện đang phàn nàn về tuyên bố kêu gọi trong 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
}
Nơi tôi đang bị mắc kẹt là dòng:
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
Tôi tin rằng tác giả ban đầu đang nỗ lực để xóa các khối bộ nhớ nơi con trỏ trở lại bởi userdataPointer()
cuộc gọi đang trỏ đến.
Với công cụ Xcode 8 tự động chuyển đổi dòng trên được quy đổi như sau:
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
Tuy nhiên Xcode tại là sau đó phàn nàn rằng Cannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer'
.
Từ nghiên cứu của tôi, thay đổi đối với dòng trả về trong userdataPointer
có vẻ chính xác, vì vậy tôi nghĩ vấn đề là với dàn diễn viên tới UnsafeMutableRawPointer. Tôi đã thử bỏ dàn diễn viên xuống UnsafeMutableRawPointer
và gọi trực tiếp ud.userdataPointer().deinitialize()
nhưng tôi gặp phải lỗi này Generic parameter 'T' could not be inferred
.
Những thứ khác tôi đã thử là chuyển đổi UnsafeMutablePointer thành UnsafeMutableRawPointer nhưng luôn dẫn đến Xcode 8 phàn nàn một điều này hay điều khác. Bất kỳ gợi ý về cách để có được điều này để làm việc?
Swift 3 migrator dường như để chuyển đổi những '.memory' để '.pointee' đúng. Bạn đúng rằng người di cư đã nhầm lẫn ở một vài nơi nhưng nhìn chung nó hoạt động trong phần lớn chuyển đổi. Tôi đã cố gắng sửa chữa nó bằng cách thay đổi dòng vi phạm thành: 'UnsafeMutablePointer (ud.userdataPointer()). Deinitialize()' Tôi nghĩ điều này là đúng nhưng nếu bạn biết nó sai tôi sẽ đánh giá cao nếu bạn để tôi biết. Cảm ơn bạn đã phân tích dài! –
Điều bạn đã làm tương tự như những gì tôi đã đề xuất. Dù bằng cách nào chúng ta cần một diễn viên hoặc khởi tạo chỉ để nói cho trình biên dịch biết tham số chung là gì khi gọi 'userdataPointer()'.Tuy nhiên, hãy cẩn thận: dòng có vấn đề trong mã cũ đã không hủy khởi tạo dữ liệu người dùng. Mã mới sẽ. Nếu cuộc gọi 'toCustomType()' tiếp theo cố gắng trả về cùng một đối tượng userdata, nó sẽ được hủy khởi tạo. Tất nhiên, tôi không biết mã, chỉ cần chia sẻ những quan sát chung. – OmniProg
Mã cũ có nghĩa là dòng này? '(ud.userdataPointer() là UnsafeMutablePointer) .destroy()'. Cảm ơn cho những người đứng đầu lên. Tôi sẽ xem xét nó. –