Cocos 2 d-xにおけるluaに関するピット

1825 ワード

先週、プロジェクト開発で奇妙な問題に遭遇しました.あるc++モジュールが解凍したバイトストリームデータがluaに渡された後、luaはバイトストリームに基づく逆シーケンス化を行う際に常にエラーが発生し、c++モジュールが読み取ったバイトストリームに問題があるのではないかと思っていましたが、debugが発見され、c++が取得したバイトストリームは確かに正しいです.そこでluaのインタフェースに走ってバイトストリームの内容と長さを印刷すると、場合によってはC++で印刷されたバイトストリームとluaが取得するバイトストリームの長さが等しくなく、luaとC++のstringに対するサポートが異なるためである可能性があることをふと思い出す.C++にバイトというタイプがないため、格納バイトストリームはcharタイプ構造に基づいたタイプの配列またはstd::stringに格納されるのが一般的であるが、この場合、char配列またはstd::stringに対してstrlenのような操作を行うと、strlenが'0'バイトに遭遇して終了すると考えられるため、char配列に格納されたバイトストリームがちょうど真ん中に'0'というバイトが含まれている場合、得られる長さに問題がある.しかしluaではstringに'0'が含まれているのは問題ない、単純にstrlenを呼び出すのではなく、lua自身がstrlen関数を実現しているので、'0'文字を含むバイトストリーム文字列を取得してもエラーは発生しない.
デバッグを行ったところ、確かにここの問題であることが判明し、cocococos 2 d-xにおけるCCLuaStackにおけるpushCCLuaValue関数のコードを変更すると上記の問題が解決し、コードは以下の通りである(注釈の部分に注意し、注釈された部分はcococos 2 d-xの元のコードである):
void CCLuaStack::pushCCLuaValue(const CCLuaValue& value)
{
    const CCLuaValueType type = value.getType();
    if (type == CCLuaValueTypeInt)
    {
        return pushInt(value.intValue());
    }
    else if (type == CCLuaValueTypeFloat)
    {
        return pushFloat(value.floatValue());
    }
    else if (type == CCLuaValueTypeBoolean)
    {
        return pushBoolean(value.booleanValue());
    }
    else if (type == CCLuaValueTypeString)
    {
        return pushString(value.stringValue().c_str(), value.stringValue().length());
//        return pushString(value.stringValue().c_str()); cocos2dx bug
    }
    else if (type == CCLuaValueTypeDict)
    {
        pushCCLuaValueDict(value.dictValue());
    }
    else if (type == CCLuaValueTypeArray)
    {
        pushCCLuaValueArray(value.arrayValue());
    }
    else if (type == CCLuaValueTypeCCObject)
    {
        pushCCObject(value.ccobjectValue(), value.getCCObjectTypename().c_str());
    }
}