Original Post
I am using the following function to call a Lua function from C++. It was taken from the official Lua site (somewhere in the manual, cannot say where exactly). Whenever I call it, it crashes on the marked lines. The debugger say the following: First-chance exception at 0x00415d35 in TestSuite.exe: 0xC0000005: Access violation writing location 0xcccccccc. Unhandled exception at 0x00415d35 in TestSuite.exe: 0xC0000005: Access violation writing location 0xcccccccc. The function is called like this: scriptmgr is valid, so don't worry about that.
bool ScriptManager::CallFunc(const std::string& sFuncName, const std::string& sFuncSignature, ...)
{
/*
note:
Because the function may return strings, call_va cannot pop the results from the stack.
It is up to the caller to pop them, after it finishes using occasional string results
(or after copying them to other buffers).
*/
va_list args;
int nArg, nRes;
const char* func = sFuncName.c_str();
const char* sig = sFuncSignature.c_str();
va_start(args, sig);
// Get Lua function.
lua_getglobal(m_pLua, func);
// Push arguments.
nArg = 0;
while (*sig)
{
switch (*sig++)
{
case 'd':
// Number type (double).
lua_pushnumber(m_pLua, va_arg(args, double));
break;
case 'i':
// Number type (int).
lua_pushnumber(m_pLua, va_arg(args, int));
break;
case 's':
// String type.
lua_pushstring(m_pLua, va_arg(args, char*));
break;
case 'b':
// Boolean type.
lua_pushboolean(m_pLua, va_arg(args, bool));
break;
// TODO: 'c' for user data (classes)
case ':':
// No arguments.
goto _end_while;
default:
return Logger::Error(L"Attempting to push invalid argument to Lua function: %c.", *(sig - 1));
}
nArg++;
luaL_checkstack(m_pLua, 1, "too many arguments!");
}
_end_while:
// Calculate number of expected results.
nRes = (int)strlen(sig);
// Call the function.
if (lua_pcall(m_pLua, nArg, nRes, 0) != 0)
{
return Logger::Error(L"Failed to run Lua function %s: %s.", func, lua_tostring(m_pLua, -1));
}
// Stack index of the first result.
nRes = -nRes;
// Get results.
while (*sig)
{
switch (*sig++)
{
case 'd':
// Number type (double).
if (!lua_isnumber(m_pLua, nRes))
{
return Logger::Error(L"Wrong return type from CallFunc! Expected 'double'.");
}
*va_arg(args, double*) = lua_tonumber(m_pLua, nRes); // <--- here
break;
case 'i':
{
// Number type (int).
if (!lua_isnumber(m_pLua, nRes))
{
return Logger::Error(L"Wrong return type from CallFunc! Expected 'int'.");
}
*va_arg(args, int*) = (int)lua_tonumber(m_pLua, nRes); // <--- here
}
break;
case 's':
// String type.
if (!lua_isstring(m_pLua, nRes))
{
return Logger::Error(L"Wrong return type from CallFunc! Expected 'string'.");
}
*va_arg(args, const char**) = lua_tostring(m_pLua, nRes); // <--- here
break;
case 'b':
// Boolean type.
if (!lua_isboolean(m_pLua, nRes))
{
return Logger::Error(L"Wrong return type from CallFunc! Expected 'bool'.");
}
*va_arg(args, bool*) = lua_toboolean(m_pLua, nRes) == 0 ? false : true; // <--- here
break;
default:
return Logger::Error(L"Attempting to get invalid result type from Lua function: %c.", *(sig - 1));
}
nRes++;
}
va_end(args);
return true;
}
int res = 0;
scriptmgr->CallFunction("testfunc", ":i", &res);