3

現在、C++ から Lua に関数を渡そうとしています。問題は、この関数に (int、int、char *、...) のパラメーターがあることです。私もLuaを使用するのはかなり新しいです。

そのため、lua スタックからすべての引数を取得し、関連する (...) 引数をベクトルに入れました。今何?

問題のコードは次のとおりです。

static int L_PrintDebug(lua_State *state)
{
MVC_View * theView = MVC_View::GetInstance(MVC_Model::GetInstace());

int n = lua_gettop(state);

// check if number of arguments is less than 3
// then we stop as not enough parameters
if(n < 3)
{
    std::cout << "Error: printDebug(number,number, char *, ... )" << std::endl;
    lua_error(state);
}

// gets parameter
int x = lua_tointeger(state, 1);
int y = lua_tointeger(state, 2);
char * words = (char*) lua_tostring(state, 3);

//Get the rest of the arguments.
std::vector<float> Numbers;
for(int i = 4;i != n; i++)
{
    if(lua_type(state,i) == LUA_TNUMBER)
    {
        float theNumber = lua_tonumber(state,i);
        Numbers.push_back(theNumber);
    }
}

// call C++ function
//This is where I'm stuck.
theView->Printw(x,y,words);
}

これは PrintW 関数です。

void MVC_View::Printw (float x, float y, const char* format, ...) 
{ 
glRasterPos2f(x,y);
char text[256];
va_list ap;
if(format==NULL)
    return;
va_start(ap,format);
    vsprintf_s(text,format,ap);
va_end(ap);

glPushAttrib(GL_LIST_BIT);
    glListBase(m_base-32);
    glCallLists(strlen(text),GL_UNSIGNED_BYTE,text);
glPopAttrib();

 } 

ここで Lua 状態に渡します。

m_theModel->theInterface.Pushfunction("PrintOnScreen",L_PrintDebug);

そのままLuaで呼び出せるようになればいいのですが、

PrintOnScreen(10, 100, "Camera 2 Pos: %f %f %f", Camx, Camy, Camz)

また

PrintOnScreen(10,100, "FPS: %f", fps)
4

1 に答える 1

4

問題は、va リストを使用して関数を呼び出す必要があるように見えますが、引数をベクトルで構築しており、実行時に va_list を構築する合理的な方法がありません。

print 関数に引数の任意のセットを取り、それらを順番に表示し (C++ のチェーンに少し似ていますcout)、va_list の使用を完全に忘れることをお勧めします。

これを行うには、引数を反復処理し、引数のタイプに基づいてバッファーに追加します。テキストと浮動小数点のみを扱う場合、これはかなり単純です。例(注:これはテストしていません):

char text[256]; /* Be careful! Buffer overflow potential for not checking lengths of sprintf and not using snprintf */
char *buf = &text[0]; /* start buf at beginning of text */
int x = lua_tointeger(state, 1);
int y = lua_tointeger(state, 2);
for (int i = 3, i < n; i++) {
    if (lua_type(state,i) == LUA_TNUMBER) {
         sprintf(buf, "%f", lua_tonumber(state,i));
    } else if (lua_type(state,i) == LUA_TSTRING) {
         sprintf(buf, "%s", lua_tostring(state,i));
    } else {
         // ERROR SOMEHOW
    }
    buf += strlen(buf); /* Move the end of buf for more appending
}
/* At this point, we've filled in text by walking through it with our buf pointer, and we have a complete string */
glPushAttrib(GL_LIST_BIT);
glListBase(m_base-32);
glCallLists(strlen(text),GL_UNSIGNED_BYTE,text);
glPopAttrib();

次に、次のように Lua を呼び出すことができます。

PrintOnScreen(10, 100, "Camera 2 Pos: ", Camx, " ", Camy, " ", Camz)

また

PrintOnScreen(10,100,"FPS: ", fps)

これは、スペースで区切る必要がある数値のリストでは少し不便ですが、コード化するのは簡単だと思います。

繰り返しますが、上記のコード例はテストされておらず、off-by-one エラーやその他のバグが含まれている可能性があることに注意してください。特に、境界チェックを追加し、sprintf の代わりに snprintf を使用する必要があります。または、構築に c++ stringstream を使用します。

于 2015-01-30T04:03:16.433 に答える