Call a Lua function from C++
Asked Answered
U

1

8

I have google high and low and found examples, but none of them seems to work (Lua 5.2).

I have a simple function in Lua

function onData ( data )
  print ( data )
end

I want to call onData from C++ and tried this:

// Create new Lua state
L = luaL_newstate();

// Load all Lua libraries
luaL_openlibs(L);

// Create co-routine
CO = lua_newthread(L);

// Load and compile script
AnsiString script(Frame->Script_Edit->Text);
if (luaL_loadbuffer(CO,script.c_str(),script.Length(),AnsiString(Name).c_str()) == LUA_OK) {
  Compiled = true;
} else {
  cs_error(CO, "Compiler error: ");    // Print compiler error
  Compiled = false;
}


// Script compiled and ready?
if (Compiled == true) {
  lua_getglobal(CO, "onData");    // <-------- Doesn't find the function
  if( !lua_isfunction(CO,-1)) {
    lua_pop(CO,1);
    return;
  }
  lua_pushlstring(CO,data,len);
  lua_resume(CO,NULL,0)
}

As you can see I'm starting my script as a co-routine so I can use the lua_yield() function on it. I have tried to look for the function in both the L and CO states.

Unfeigned answered 10/12, 2013 at 12:52 Comment(0)
M
4

luaL_loadbuffer loads the script but does not run it. onData will only be defined when the script is run.

Try calling luaL_dostring instead of luaL_loadbuffer.

Or add lua_pcall(CO,0,0,0) before lua_getglobal.

Moreover, you need lua_resume(CO,NULL,1) to pass data to onData.

Margarito answered 10/12, 2013 at 12:57 Comment(8)
But lua_loadbuffer() compiles the script and places it on the stack for execution, so it should be known. luaL_dostring() will compile AND execute the script, after that the chunk is poped of the stack. As you can see I need to use the lua_resume so I can use the lua_yield() function. If I run the script first, then other code than the desired function will run too. I only want to run that function, nothing else.Unfeigned
@MaxKielland lhf is one of the creators of Lua. He probably knows very well what he is talking about. So I suggest actually trying his suggestion and seeing if it works (because it probably will).Fungoid
@MaxKielland, if you want to define onData, you need to run the script. Also, you need lua_resume(CO,NULL,1) to pass data to onData.Margarito
@H2CO3 No doubt about it, but his suggestion doesn't produce the result I need. I can't run the whole script first because then everything else will run too.Unfeigned
@MaxKielland, I'm afraid you'll have to change your design or place the definition of onData in a separate chunk.Margarito
@Margarito all right so the compiler can't figure out where the functions are and provide that information... I guess I have to go back to the drawing board again...Unfeigned
@MaxKielland what if you place the "executing" parts of the script into say a "main" function? This will insulate it from execution when running your script. It might be easier to think of luaL_load* functions as wrapping your script in its entirety in an anonymous function and leaving that function on the stack. Until you actually run that anonymous function, none of the stuff in the script comes into existence.Sneak
@Sneak Yes, I had the same thought. The script is arbitrary and the user can write whatever he likes, so I can't guarantee there will not be any global code. So it comes down to documentation I guess...Unfeigned

© 2022 - 2024 — McMap. All rights reserved.