2016-10-05 4 views
6

मैं स्विफ्ट 2 से स्विफ्ट 3 तक एक लुआ पुल को बदलने की कोशिश कर रहा हूं। मैं मूल लेखक नहीं हूं इसलिए लाइब्रेरी के पहलू हैं जिन्हें मैं बहुत अच्छी तरह से नहीं जानता और मूल लेखक काम करना जारी रखने में रुचि नहीं रखते हैं परियोजना। मेरे पास अधिकांश रूपांतरण किए गए हैं लेकिन वहां एक जगह है जहां मैं फंस गया हूं और पता नहीं लगा सका। मैंने एसओ और इंटरनेट पर खोज करने की कोशिश की है लेकिन मुझे कुछ भी नहीं मिला जो समस्या को हल करने में मेरी मदद कर सकता है।एक सी फंक्शन से 'void *' वापसी को स्विफ्ट 3 में 'UnsafeMutableRawPointer' में कैसे परिवर्तित करें?

अगर कोई पूर्ण स्रोत कोड देख में रुचि रखता है, यहाँ GitHub पर परियोजना की मेरी कांटा है: https://github.com/weyhan/lua4swift (मेरे परिवर्तन Swift3 शाखा में है)

मुझे सेटअप त्रुटि मैं करने के लिए संदर्भ की अनुमति दें मैं अटक गया उपयोगकर्ता आईडीटा श्रेणी है, खासकर विधि userdataPointer<T>() -> UnsafeMutablePointer<T> में सी फ़ंक्शन lua_touserdata उपयोगकर्ता डेटा का ब्लॉक पता void * सूचक प्रकार के रूप में देता है।

मूल स्विफ्ट 2 में लिखे कोड:

return UnsafeMutablePointer<T>(ptr) 

मैं इसे ठीक करने के बाद:

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 } 

} 

Xcode 8 प्रवास उपकरण के साथ रूपांतरण के बाद, Xcode त्रुटि Cannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)' साथ वापसी लाइन के बारे में शिकायत कर रहा है के साथ:

return (ptr?.assumingMemoryBound(to: T.self))! 

ऊपर दिए गए परिवर्तन के बाद, अब एक्सकोड 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 
} 

मैं कर रहा हूँ कहाँ अटक लाइन है:

(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy() 

मेरा मानना ​​है कि मूल लेखक स्मृति ब्लॉक जहां सूचक लौटे खाली करने के लिए प्रयास कर रहा है userdataPointer() द्वारा कॉल इंगित कर रहा है।

Xcode 8 ऑटो माइग्रेशन टूल ऊपर की रेखा से नीचे के रूप में परिवर्तित किया जाता है के साथ

:

(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize() 

हालांकि Xcode अब शिकायत है कि Cannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer' तो है।

मेरे शोध से, userdataPointer में रिटर्न लाइन में परिवर्तन सही लगता है, इसलिए मुझे लगता है कि यह समस्या असुरक्षित MawableRawPointer को कास्ट के साथ है। मैंने UnsafeMutableRawPointer पर कास्ट छोड़ने की कोशिश की है और सीधे ud.userdataPointer().deinitialize() का आह्वान किया है लेकिन मुझे यह त्रुटि Generic parameter 'T' could not be inferred मिलती है।

अन्य चीजें जो मैंने कोशिश की है वह असुरक्षित म्यूचुअल पॉइंटर को असुरक्षित म्यूचुअल राउपॉन्टर में परिवर्तित करना है, लेकिन यह हमेशा एक्सकोड 8 में एक चीज़ या किसी अन्य की शिकायत करता है। काम करने के लिए इसे कैसे प्राप्त करें इस पर कोई सुझाव?

उत्तर

3

जैसा कि आप पहले से ही पता लगा सकते हैं, स्विफ्ट 3 पॉइंटर्स की बात करते समय बेहतर प्रकार की सुरक्षा प्रदान करने का प्रयास करता है। UnsafeMutablePointer अब ज्ञात प्रकार के उदाहरण के लिए केवल एक सूचक का प्रतिनिधित्व कर सकता है।स्विफ्ट 2 में, एक सी void * का प्रतिनिधित्व UnsafeMutablePointer<Void> द्वारा किया गया था, जो शून्य और गैर-शून्य पॉइंटर्स को उसी तरह से इलाज करने की इजाजत देता है, जिसमें बिंदु-प्रकार के डी-प्रारंभकर्ता को कॉल करने का प्रयास करने सहित, destroy() विधि में विधि है कोड की समस्या पैदा करने वाले लाइन करता है:

(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy() 

स्विफ्ट 3 में pointee पर de-प्रारंभकर्ता UnsafeMutablePointer संरचना के deinitialize() विधि का उपयोग कर कहा जाता है। ऐसा प्रतीत होता है कि माइग्रेशन सहायक उलझन में आया। लाइन

(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize() 

थोड़ा भावना क्योंकि (1) UnsafeMutablePointerUnsafeMutableRawPointer करने के लिए as का उपयोग कर नहीं बदला जा सकता है; (2) UnsafeMutableRawPointerdeinitialize() विधि नहीं है। स्विफ्ट 3 में, UnsafeMutableRawPointervoid* का प्रतिनिधित्व करने के लिए एक विशेष प्रकार है। यह वास्तव में काफी समझ में आता है कि माइग्रेशन टूल ने यह गलती क्यों की: इसे destroy()deinitialize() और UnsafeMutablePointer<Void> के साथ संबंधित स्विफ्ट 3 प्रकार UnsafeMutableRawPointer के साथ अंधाधुंध रूप से बदल दिया गया, यह समझने के बिना कि रूपांतरण काम नहीं करेगा।

मुझे समझ में नहीं आता कि एक शून्य सूचक पर destroy() क्यों कॉल करना स्विफ्ट 2 में काम करेगा। शायद यह प्रोग्राम में एक बग था या कुछ कंपाइलर चाल ने सही डी-प्रारंभकर्ता को बुलाया था। कोड के बारे में पर्याप्त जानकारी के बिना, मैं यह पता लगाने के लिए विश्लेषण करने के लिए अधिक विशिष्ट नहीं हो सकता कि यह पता लगाने के लिए कि destroy() कहलाता है। उदाहरण के लिए, अगर हम निश्चित रूप से पता यह हमेशा प्लेसहोल्डर प्रकार T निम्न पंक्ति पर इस्तेमाल किया है कि:

let o: T = ud.toCustomType() 

तो हमलावर लाइन बस हो जाता है

(ud.userdataPointer() as UnsafeMutablePointer<T>).deinitialize() 

हम करने के लिए कोष्ठक में रूपांतरण की जरूरत है संकलक को जेनेरिक पैरामीटर का अनुमान लगाने की अनुमति दें।

एक दिलचस्प समस्या लाने के लिए धन्यवाद। बीटीडब्ल्यू, एक बार जब आप इस बाधा को खत्म कर देते हैं, तो आप अन्य समस्याओं में भाग लेने की संभावना रखते हैं। एक बात जो बाहर निकलती है वह है कि UnsafeMutablePointer में स्विफ्ट 3 में .memory नहीं है; आपको इसके बजाय .pointee का उपयोग करना होगा।

यहां एक अपडेट है। लिनक्स पर स्विफ्ट 2.2 के साथ खेलने के बाद, मुझे एहसास हुआ कि destroy() पर पर UnsafeMutablePointer<Void> पर डाला गया है, ए के डिनाइनिलाइज़र को कॉल नहीं करेगा, भले ही उसके पास एक हो। तो, आपको लगता है कि लाइन के साथ सावधान रहना होगा ...

+0

स्विफ्ट 3 migrator उन '.memory' कन्वर्ट करने के लिए लगता है 'पॉइंट' सही करने के लिए। आप सही हैं कि माइग्रेटर कुछ स्थानों पर भ्रमित हो गया लेकिन आम तौर पर यह अधिकांश रूपांतरणों में काम करता है। मैंने अपमानजनक रेखा को बदलकर इसे ठीक करने में कामयाब रहा है: 'UnsafeMutablePointer (ud.userdataPointer())। Deinitialize() ' मुझे लगता है कि यह सही है लेकिन यदि आपको पता है कि यह गलत है तो मैं आपकी सराहना करता हूं मुझे पता है। लंबे विश्लेषण के लिए धन्यवाद! –

+0

आपने जो किया वह वही काम करता है जैसा मैंने सुझाया था। किसी भी तरह से हमें कंप्रेसर को बताने के लिए केवल एक कास्ट या प्रारंभिकता की आवश्यकता होती है जो 'userdataPointer() 'को कॉल करते समय जेनेरिक पैरामीटर होता है।सावधान रहें, हालांकि: पुराने कोड में समस्याग्रस्त रेखा ने उपयोगकर्ता डेटा को प्रारंभ नहीं किया था। नया कोड होगा। यदि बाद में 'toCustomType()' कॉल एक ही उपयोगकर्ता डेटा ऑब्जेक्ट को वापस करने का प्रयास करता है, तो यह पहले ही डी-प्रारंभिक होगा। बेशक, मुझे सामान्य अवलोकन साझा करने के लिए कोड नहीं पता है। – OmniProg

+0

पुराना कोड इस लाइन का अर्थ है? '(ud.userdataPointer() UnsafeMutablePointer ) .destroy()'। सर उठाने के लिए धन्यवाद। मैं इसमें देख लूंगा। –

1

बजाय इसे कास्ट करने के लिए कोशिश कर के UnsafeMutableRawPointer का उदाहरण बनाकर प्रयास करें:

UnsafeMutableRawPointer<T>(ud.userdataPointer()).destroy()

+0

हालांकि मैं जिस फॉर्म का उपयोग करता था वह यह था: 'असुरक्षित म्यूचुअल पॉइंटर (ud.userdataPointer())। Deinitialize() ' धन्यवाद। –

संबंधित मुद्दे