ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
lua_pcall
... Like lua_call, lua_pcall always removes the function and its arguments from the stack.
So when you call lua_pcall with "state" the second time the stack is empty.
I only know of two ways do this:
call luaL_loadfile(), which performs an i/o operation, after calling lua_pcall to push your data onto the stack each time you want to execute the code in the file.
load the file once into a string and push the string onto the stack before each lua_pcall.
I have refrained from knocking this off the zero-reply until someone more knowledgable answered. Now that norobro has provided a much better response, I'll add my own incomplete observation..
Quote:
Originally Posted by goingbackwards
Here's my example, the result from step 3 is "attempt to call a string value"...
Which would indicate to me that state at that point is not a valid lua_State *. Norobro's mention of stack exhaustion would seem to point in the same direction.
Ah, excellent! Just coming back to this, thankyou...
So the state is still valid, but its just popped off the instruction stack, and that needs to be copied in again using luaL_loadbuffer()... That makes sense (esp with an analogy to filling the cache before letting the ALU rip???)... I'll give it a go!
#include "LuaEngScript.h"
#include <cmath>
// ===================================================================
// START API
// ===================================================================
static int l_sin (lua_State *L)
{
double d = luaL_checknumber(L, 1);
lua_pushnumber(L, 53); // sin(d));
return 1; // number of results
}
// ===================================================================
// END API
// ===================================================================
LuaEngScript::LuaEngScript(std::string fn)
{
filename = "";
script = "";
state = NULL;
if(fn != "")
{
load(fn);
}
}
LuaEngScript::~LuaEngScript()
{
if(state)
{
lua_close(state);
}
}
void LuaEngScript::load(std::string fn)
{
filename = fn;
if(filename == "")
{
}
else
{
// LOAD FILE
file_load(filename);
//lua_State *
state = luaL_newstate();
luaL_openlibs(state);
lua_pushcfunction(state, l_sin);
lua_setglobal(state, "mysin");
// ADD A TABLE OF FUNCTIONS
lua_newtable(state); // We will pass a table
lua_pushstring(state, "sin"); // Push the table index
lua_pushcfunction(state, l_sin);
//lua_pushnumber(state, i*2); // Push the cell value
lua_rawset(state, -3); // Stores the pair in the table
lua_pushstring(state, "cos"); // Push the table index
lua_pushcfunction(state, l_sin);
//lua_pushnumber(state, i*2); // Push the cell value
lua_rawset(state, -3); // Stores the pair in the table
// By what name is the script going to reference our table?
lua_setglobal(state, "eng");
//luaL_loadbuffer(state, script.c_str(), script.length(), script.c_str());
//lua_pcall(state, 0, LUA_MULTRET, 0);
}
}
void LuaEngScript::file_load(std::string fn)
{
std::ifstream file(fn);
//std::string str( (std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()) );
script = std::string( (std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()) );
file.close();
//script = str;
}
void LuaEngScript::call_init()
{
luaL_loadbuffer(state, script.c_str(), script.length(), script.c_str());
lua_pcall(state, 0, LUA_MULTRET, 0);
//double x = 10;
//double y = 3;
double z;
// push functions and arguments
lua_getglobal(state, "init"); // function to be called
//lua_pushnumber(state, x); // push 1st argument
//lua_pushnumber(state, y); // push 2nd argument
// do the call (2 arguments, 1 result)
//if (lua_pcall(state, 2, 1, 0) != 0)
if (lua_pcall(state, 0, 1, 0) != 0) // zero args, one result
{
std::cout << "LuaEngScript::call_init() Error call" << std::endl;
//error(state, "error running function `f': %s", lua_tostring(state, -1));
print_error(state);
return;// stack;
}
// retrieve result
if (!lua_isnumber(state, -1))
{
std::cout << "LuaEngScript::call_init() Error return result" << std::endl;
//error(state, "function `mult' must return a number");
print_error(state);
return;// stack;
}
z = lua_tonumber(state, -1);
lua_pop(state, 1); /* pop returned value */
//printf("\nResult: %0.2f\n", z);
std::cout << "LuaEngScript::call_init() Result: " << z << std::endl;
//lua_close(state);
}
void LuaEngScript::call_step(float delta)
{
luaL_loadbuffer(state, script.c_str(), script.length(), script.c_str());
lua_pcall(state, 0, LUA_MULTRET, 0);
std::vector<double> data;
add_global_table_num(state, "foo", data);
std::map<std::string,std::string> data2;
data2.insert( std::pair<std::string,std::string>("one", "apples") );
data2.insert( std::pair<std::string,std::string>("two", "pairs") );
add_global_table_strings(state, "mydata", data2);
//double x = 10;
//double y = 3;
double z;
// push functions and arguments
lua_getglobal(state, "step"); // function to be called
lua_pushnumber(state, delta); // push 1st argument
//lua_pushnumber(state, y); // push 2nd argument
// do the call (2 arguments, 1 result)
//if (lua_pcall(state, 2, 1, 0) != 0)
if (lua_pcall(state, 1, 1, 0) != 0) // one arg, one result
{
std::cout << "LuaEngScript::call_step() Error call" << std::endl;
//error(state, "error running function `f': %s", lua_tostring(state, -1));
print_error(state);
return;// stack;
}
// retrieve result
if (!lua_isnumber(state, -1))
{
std::cout << "LuaEngScript::call_step() Error return result" << std::endl;
//error(state, "function `mult' must return a number");
print_error(state);
return;// stack;
}
z = lua_tonumber(state, -1);
lua_pop(state, 1); /* pop returned value */
//printf("\nResult: %0.2f\n", z);
std::cout << "LuaEngScript::call_step() Result: " << z << std::endl;
//lua_close(state);
}
void LuaEngScript::print_error(lua_State* state)
{
//std::cout << "LuaEngScript::print_error()" << std::endl;
// The error message is on top of the stack.
// Fetch it, print it and then pop it off the stack.
const char* message = lua_tostring(state, -1);
puts(message);
lua_pop(state, 1);
}
std::vector<std::string> LuaEngScript::lua_get_stack(lua_State *L)
{
// GRAB STACK AS VECTOR OF STRINGS
std::vector<std::string> ls;
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++)
{
ls.push_back((std::string)lua_tostring(L, i));
}
return ls;
}
void LuaEngScript::add_global_table_num(lua_State *state, std::string name, std::vector<double> data)
{
// * Ok, now here we go: We pass data to the lua script on the stack.
// * That is, we first have to prepare Lua's virtual stack the way we
// * want the script to receive it, then ask Lua to run it.
lua_newtable(state); /* We will pass a table */
// * To put values into the table, we first push the index, then the
// * value, and then call lua_rawset() with the index of the table in the
// * stack. Let's see why it's -3: In Lua, the value -1 always refers to
// * the top of the stack. When you create the table with lua_newtable(),
// * the table gets pushed into the top of the stack. When you push the
// * index and then the cell value, the stack looks like:
// *
// * <- [stack bottom] -- table, index, value [top]
// *
// * So the -1 will refer to the cell value, thus -3 is used to refer to
// * the table itself. Note that lua_rawset() pops the two last elements
// * of the stack, so that after it has been called, the table is at the
// * top of the stack.
for (int i = 1; i <= 5; i++)
{
lua_pushnumber(state, i); // Push the table index
lua_pushnumber(state, i*2); // Push the cell value
lua_rawset(state, -3); // Stores the pair in the table
}
// By what name is the script going to reference our table?
lua_setglobal(state, name.c_str());
}
void LuaEngScript::add_global_table_strings(lua_State *state, std::string name, std::map<std::string,std::string> data)
{
// push new table
lua_newtable(state);
// add data
//for(unsigned int i = 0; i < data.size(); i++)
for(std::map<std::string,std::string>::iterator it=data.begin(); it!=data.end(); ++it)
{
lua_pushstring(state, it->first.c_str()); // Push the table index
lua_pushstring(state, it->second.c_str()); // Push the cell value
lua_rawset(state, -3); // Stores the pair in the table
}
// lua variable name
lua_setglobal(state, name.c_str());
}
with a lua file of:
Code:
io.write("ImgBug: main.lua\n");
function init (a)
io.write("ImgBug: init()\n");
return 0
end
function step (delta)
io.write("ImgBug: step()\n");
print(" delta", delta)
print(" sin", mysin(10))
print(" eng.sin", eng.sin(10))
--test_01()
print(" global table", foo[2])
print(" global table", mydata.one)
--N = N + 1
--local N = N + 1
N = 0
--return (x^2 * math.sin(y))/(1 - x)
return N
end
function test_01()
-- TABLE EXAMPLE
local t = {}
t["foo"] = 123 -- assign the value 123 to the key "foo" in the table
t[3] = "bar" -- assign the value "bar" to the key 3 in the table
print("foo", t["foo"])
print("3", t[3])
t = {["foo"] = "bar", [123] = 456}
print(".foo", t.foo)
end
function f (a, b)
return a * b
end
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.