【问题标题】:C++ and Lua integration with arguments (...) (Lua 5.1)带参数的 C++ 和 Lua 集成 (...) (Lua 5.1)
【发布时间】:2015-03-29 12:08:15
【问题描述】:

我目前正在尝试将一个函数从 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)

【问题讨论】:

    标签: c++ lua lua-api


    【解决方案1】:

    问题似乎是您需要使用 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)
    

    这对于需要空格分隔的数字列表来说稍微不方便,但我认为更容易编码。

    再次注意,上面的示例代码未经测试,可能包含错误或其他错误。特别是您应该添加边界检查并使用 snprintf 而不是 sprintf。或者,使用 c++ 字符串流进行构造。

    【讨论】:

    • 足够接近让我努力寻找答案:) 非常感谢!
    猜你喜欢
    • 2011-11-26
    • 2012-06-28
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    相关资源
    最近更新 更多