2016-10-05 8 views
6

私はスイフト2からスイフト3にルアブリッジを変換しようとしています。私は元の著者ではないので、私はよく分からないライブラリの側面があり、元の著者は作業を続けることに興味がないようですプロジェクト。私は変換のほとんどを行っているが、私は固執していると把握できない1つの場所が残っている。私はSOとインターネットで検索しようとしましたが、問題を解決するのに役立つものは見つかりませんでした。C関数から 'UnsafeMutableRawPointer'への 'void *'戻り値をSwift 3でどう変換するのですか?

誰もが完全なソースコードを見に興味がある場合は、ここではプロジェクトの私のフォークはgithubの上にある:https://github.com/weyhan/lua4swift(私の変更はSwift3ブランチである)

は私、私は「エラーに設定コンテキストを許可しますついています。 Userdataクラスがあり、具体的にはuserdataPointer<T>() -> UnsafeMutablePointer<T>メソッドのlua_touserdataは、void *というポインタ型のuserdataのブロックアドレスを返します。

スウィフト2で書かれたオリジナルコード:私はそれを修正しました

return UnsafeMutablePointer<T>(ptr) 

:Xcodeの8移行ツールを使用して変換した後

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はエラーCannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)'と戻りラインについて不平を言っていますwith:

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

これ以降、Xcode 8今createCustomTypeに呼び出し元の文の文句を言っている:私は原作者がポインタが返されたメモリ・ブロックをクリアしようとしていると信じて

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

:私は立ち往生してい

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 
} 

がラインでありますuserdataPointer()によってコールが指し示しています。 Xcodeの8自動移行ツールで

上の行は、以下のように変換される:

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

Xcodeのは、今、そのCannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer'を訴えるているが。

私の研究では、userdataPointerのリターンラインへの変更が正しいと思われるので、問題はUnsafeMutableRawPointerへのキャストであると思います。キャストをUnsafeMutableRawPointerに落としてみてud.userdataPointer().deinitialize()を直接呼び出しましたが、このエラーはGeneric parameter 'T' could not be inferredです。

私が試みたその他のことは、UnsafeMutablePointerをUnsafeMutableRawPointerに変換することですが、Xcode 8は常に1つまたは複数の不具合を引き起こします。どのようにこれを動作させるための任意の提案?

答えて

3

既に知っているかもしれないが、Swift 3では、ポインターに関してより良い型の安全性を提供しようとしています。 UnsafeMutablePointerは、既知の型のインスタンスへのポインタのみを表現できるようになりました。Swift 2では、C void *UnsafeMutablePointer<Void>で表され、void型ポインターと非voidポインターを同じ方法で扱うことができ、pointed-to型の脱初期化子を呼び出そうとしましたが、destroy()コードの問題の行を行います。スイフト3において

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

を指示先にデイニシャライザはUnsafeMutablePointer構造のdeinitialize()方法を使用して呼び出されます。移行アシスタントが混乱しているようです。 (1)UnsafeMutablePointerUnsafeMutableRawPointerからasを使用して変換することができないので、ライン

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

はほとんど意味がありません。 (2)UnsafeMutableRawPointerにはdeinitialize()メソッドがありません。スウィフト3では、UnsafeMutableRawPointervoid*を表す特別なタイプです。なぜ、移行ツールがこのミスを犯したのか、実際には理解できます。をdeinitialize()UnsafeMutablePointer<Void>と対応するSwift 3タイプUnsafeMutableRawPointerで盲目的に置き換えても、変換が機能しないことはわかりません。

voidポインタ上のdestroy()をSwift 2で呼び出すのはなぜか分かりません。これは、プログラムのバグか、正しいデイニシャライザの呼び出しを許可したコンパイラのトリックかもしれません。コードについて十分に理解していなければ、それを分析してdestroy()が呼び出されたそのポインターが指している型が何であるか把握することを提案するよりも具体的ではありません。我々は確かに知っている場合たとえば、それは常に次の行に使用プレースホルダタイプTであること:

let o: T = ud.toCustomType() 

は、問題のある行は、単純に

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

我々はカッコ内への変換が必要になり、コンパイラが汎用パラメータを推論できるようにします。

興味深い問題を提起していただきありがとうございます。ところで、この障害を乗り越えたら、他の問題にぶつかる可能性が高いです。飛び出すことの1つは、スウィフト3にUnsafeMutablePointerには.memoryがないことです。代わりに.pointeeを使用する必要があります。

ここにアップデートがあります。 LinuxのSwift 2.2でプレイした後、UnsafeMutablePointer<Void>としてUnsafeMutablePointer<A>キャストのdestroy()を呼び出すと、Aの初期化子があるとしてもそれは呼び出されません。だから、あなたは、その行に注意する必要が...

+0

スウィフト3移行では、これらの '.memory'を変換するように思われます権利を「指示する」。あなたは、いくつかの場所で混乱してしまったマイグレーション担当者が正しいですが、一般的に、ほとんどの変換で動作します。 「UnsafeMutablePointer (ud.userdataPointer())。deinitialize() ' これは正しいと思いますが、間違っていると思ったら、私は知っている。長い分析をありがとう! –

+0

あなたがしたことは、私が提案したものと同じです。いずれにしても、 'userdataPointer()'を呼び出すときにジェネリックパラメータが何であるかをコンパイラに伝えるために、キャストまたは初期化が必要です。ただし、古いコードの問題のある行はユーザーデータを初期化しませんでした。新しいコードが作成されます。後続の 'toCustomType()'呼び出しが同じuserdataオブジェクトを返そうとすると、それはすでに初期化解除されます。もちろん、私はコードを知らず、一般的な観察を共有するだけです。 – OmniProg

+0

この行を意味する古いコードですか? '(ud.userdataPointer()としてUnsafeMutablePointer ).destroy()'を実行します。ヘッドアップをありがとう。私はそれを調べるでしょう。 –

1

ではなく、それをキャストしようとしているのUnsafeMutableRawPointerのインスタンスを作成してみてください:

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

+0

私が使用しているフォームはこれでした: 'UnsafeMutablePointer (ud.userdataPointer())。deinitialize()' ありがとう。 –

関連する問題