広告のSDKをアップデートしなければいけなかったので、久しぶりにAndroidのビルドをしようと思い、Android Studioをアップデートしてビルドしてみたら、案の定うまくいかない。cocos2dもアップデートしたり、他のSDKもアップデートして、色々エラーを取り除いて、最後に残ったのが、

undefined reference to non-virtual thunk to …

というエラー。みつからないのは、cocos2dのTextureProtocolクラスの仮想関数(のnon-virtual thunk)。このクラスはSpriteクラスで多重継承されていて、エラーが出るのは自分でSpriteクラスを派生させた独自クラス。

この部分のコードは前から変わってなく、変わったのはツールチェインだけだし、こんなのGCCのバグだろうと思うのだけど、とりあえずコンパイルを通したかったので、回避方法をみつけました。

まず、cocos2dのSpriteクラスを見ると次のように宣言されてます。

non-virtual thunkというのをGoogleで調べると「What is a non-virtual thunk?」という投稿がみつかって、そこに詳しく書いてあるんだけど、簡単に説明すると、TextureProtocolのポインタとしてSpriteクラスの仮想関数が呼ばれたときに、thisポインタを調整するための関数みたいです。コードで表すと

という感じになるでしょうか。多重継承しているので、thisポインタをそのままSpriteとして使うことはできず、static_castして正しい位置を指すようにずらさないといけません。

cocos2dはスタティックライブラリとしてアーカイブされていて、それをアプリの.soにリンクするときに、このようなnon-virtual thunkがみつからなくなるようです。アプリ側はSpriteを継承したクラスはあるものの、TextureProtocolの関数はオーバーライドしていないので、本来ならSpriteのnon-virtual thunkをそのまま使えるはずだし、実際コンパイラはそれを使おうとしているけれど、エラーがでてしまうのです。

しかたがないので、アプリ側でSpriteを継承したクラスでも、TextureProtocolの関数をオーバーライドしてエラーを回避することにしました。

どう考えてもこんな関数追加するなんて無駄だし、やっぱりGCCのバグだよね?

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Anti Spam Code *