我需要执行一个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));
}
答案 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)
存储该脚本的结果