【问题标题】:Executing Lua function from a string从字符串执行 Lua 函数
【发布时间】:2016-09-07 15:35:08
【问题描述】:

我需要执行一个 lua 函数,它是 XML 文件的一部分。我将解析 XML 并将整个函数加载为字符串。

当我尝试执行 lua_pcall 时,它给了我attempt to call a nil value。 但是当我试图删除函数部分并单独使用内部逻辑时,它对我来说很好。我需要了解是否需要执行任何其他步骤才能作为函数执行。

初始化:

/* the Lua interpreter */
lua_State *luaState;
// initialize Lua 
luaState = luaL_newstate();
lua_register(luaState, "getValue", get_value);
lua_register(luaState, "setValue", set_value);
// load Lua base libraries 
luaL_openlibs(luaState);

工作: XML

-- lua script to be executed by this algorithm
-- use following API calls to get and set function block data
-- local IN1 = getValue("IN1")
-- setValue("OUT1", value)
 setValue("RequestAccepted", "true");

-- lua script

C++ 代码:

TAlgoTable::iterator iter = algoTable.find("RequestAccepted");
if (luaL_dostring(luaState, iter->second.c_str()))
{
    printf("Failure at Algorithm : 'RequestAccepted' Reason : %s", lua_tostring(luaState, -1));
}

不工作:

 -- lua script to be executed by this algorithm
function RequestAccepted()
 -- use following API calls to get and set function block data
 -- local IN1 = getValue("IN1")
 -- setValue("OUT1", value)
 setValue("RequestAccepted", "true");

end -- lua script

C++ 代码:

lua_getglobal(luaState, "RequestAccepted"); // function to be called 
if (lua_pcall(luaState, 0, 0, 0)) {
    printf("Failure at Algorithm : 'RequestAccepted' Reason : %s", lua_tostring(luaState, -1));
}

【问题讨论】:

  • 在第一个示例中,您调用lua_dostring() 来解析和执行Lua 代码。在第二个例子中,你不是,除非你忽略了那一点。

标签: c++ xml lua


【解决方案1】:

我发现并理解我需要将函数加载到缓冲区中。 以下链接帮助我解决了 http://gouthamanbalaraman.com/blog/minimal-example-lua-function-cpp.html

【讨论】:

    【解决方案2】:

    在我的一个项目中,我这样做的方式是使用(原谅格式、复制和粘贴)创建 Lua 引用:

    int SParamSchemaNode::parseScript(lua_State* L,
                                      const char* arglist,
                                      const char* body)
    {
    std::ostringstream bufToParse;
    
    // save old stack top so we can clean up errors from the first
    // try if the second succeeds
    int oldStackTop = lua_gettop(L);
    bufToParse << "return function(" << arglist << ") return ("
               << body << ") end";
    if (luaL_dostring(L, bufToParse.str().c_str()))
    {
        int parseError1_pos = lua_gettop(L);
        bufToParse.str(std::string());  // reset bufToParse string to empty
        bufToParse << "return function(" << arglist << ") "
                   << body << " end";
        if (luaL_dostring(L, bufToParse.str().c_str()))
        {
            // since the error message includes the script which we're trying
            // to parse, the result has unbounded length; so use another
            // ostringstream to hold the error message
            std::ostringstream errmsg;
            errmsg << "Errors parsing the following script:" << std::endl;
            errmsg << body << std::endl << std::endl;
            errmsg << "Parser error when interpreting as an expression:" << std::endl;
            errmsg << lua_tostring(L, parseError1_pos) << std::endl << std::endl;
            errmsg << "Parser error when interpreting as a function body:" << std::endl;
            errmsg << lua_tostring(L, -1);
            ERROR_ReportError(errmsg.str().c_str());
        }
    }
    if (DEBUG)
    {
        std::cout << "Successfully loaded chunk: " << bufToParse.str() << std::endl;
    }
    int ref = luaL_ref(L, LUA_REGISTRYINDEX);
    lua_settop(L, oldStackTop);
    return ref;
    }
    

    然后我将它存储在(例如)SParameterDefinition::m_applicableScriptRef 成员中,并使用:

    bool SParameterDefinition::isApplicable(SAbstractComponent* cmpt, int index)
    {
    if (m_applicableScriptRef == LUA_NOREF)
    {
        return true;
    }
    
    lua_State* L = schema()->luaState();
    // fetch the function to call from the registry
    lua_rawgeti(L, LUA_REGISTRYINDEX, m_applicableScriptRef);
    // push the "cmpt" argument
    SWIG_UC_push_SAbstractComponent(L, cmpt);
    int nargs = 1;
    if (m_isInstanced)
    {
        lua_pushnumber(L, index);
        nargs++;
    }
    // protected call of the function (nargs arguments, 1 result,
    //   no special error handler function)
    int script_result = lua_pcall(L, nargs, 1, 0);
    if (script_result != 0)
    {
        std::ostringstream errmsgBuf;
        errmsgBuf << "Error while calling applicable script for "
                  << "parameter " << m_name << ":\n";
        errmsgBuf << lua_tostring(L, -1);
        ERROR_ReportError(errmsgBuf.str().c_str());
    }
    if (! lua_isboolean(L, -1))
    {
        report_type_error("Applicable",
                          m_name.c_str(), "boolean",
                          luaL_typename(L, -1));
    }
    bool result = (lua_toboolean(L, -1) != 0);
    lua_pop(L, 1);
    return result;
    }
    

    您可能不需要这里的全部复杂性,但要点是将主体包裹在 return function() ... end 中,使用 luaL_dostring 对其进行评估,然后使用 luaL_ref(L, LUA_REGISTRYINDEX) 存储该脚本的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-07
      • 2010-12-19
      • 2017-10-26
      • 1970-01-01
      • 2019-11-07
      • 2011-03-08
      • 2016-07-02
      • 1970-01-01
      相关资源
      最近更新 更多