从字符串执行Lua函数

时间:2016-05-12 02:09:38

标签: c++ xml lua

我需要执行一个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));
}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

在我的一个项目中,我这样做的方法是使用(原谅格式化,复制和粘贴)创建一个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)存储该脚本的结果