Sunday, September 1, 2013

XCode4.6で、Apple March-O Linker Error の対応


cocos2d-x の CCLabelTTF(テキストラベル)を管理するクラスを自作していたところ、途中からコンパイルが通らなくなって困った。何をしたかというと、
1)CCLabelTTF をメンバ変数に持つ自作クラス(SSMsgBoxDQ)を作成。
2)上記クラス内で自作関数(string 対応のprintfなど)を使用しているので、自作関数群を別ファイル(SSlib.h と SSlib.cpp)に抜き出し、SSMsgBoxからヘッダを読み込む。
3)その状態でコンパイル。

すると、ビルドが失敗し、タイトルのエラー「Apple March-O Linker Error」が出た。
linker command failed with exit code 1 (use -v to see invocation)

だそうである。正直よくわからないので、Webで調べてみると、多かったのが「プロジェクトに新規ファイル(この場合"SSlib.h")が認識されていない。ということ。

そこでプロジェクト>BuildPhases の、ビルド対象ファイルに SSlib.cpp が追加されていることを確認。きちんと追加されている。どうやら問題はここではないようだ。クラスからライブラリのヘッダを読み込んでいるのだが、クラスがおかしいのか、ライブラリがおかしいのか???
//  DQ風ウィンドウマネージャ
//  SSMsgBoxDQ.h

#include "SSlib.h"  // 関数ライブラリ

class SSMsgBoxDQ : public CCObject { ...
あれこれ修正して悩んだ結果、「ライブラリのヘッダ内に関数プロトタイプだけでなく、関数の実体を定義していた」のが原因だと判明。

それまで、「c++の関数ライブラリを作るのに、プロトタイプと関数定義を別々に書かないといかんのだろうか?面倒だから .h プロトタイプを書かないで関数定義し、.cpp は空っぽにしてみよう。」とやっていたので、そのためにコンパイルが通らなかったのだ。別々に書き直したら、エラー解消。横着はいかんなと反省。。。
以下、関数プロトタイプと関数本体をきちんと別々に記述したもの(ソースの抜粋)です。
// 関数ライブラリ "SSlib.h"
string strRepeat(const char* str, int count);
// 関数ライブラリ "SSlib.cpp"
#include "SSlib.h"

// 繰り返し文字列を得る(マルチバイト対応)
string strRepeat(const char* str, int count) {
    CCAssert(count>=0 && count<255, __FUNCTION__);
    
    string sRet;
    for(int i=0; i< count; ++i){
        sRet += str;
    }
    
    return sRet;
}

No comments:

Post a Comment