7

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.

lhf
  • 70,581
  • 9
  • 108
  • 149
Max Kielland
  • 5,627
  • 9
  • 60
  • 95

1 Answers1

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.

lhf
  • 70,581
  • 9
  • 108
  • 149
  • 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. – Max Kielland Dec 10 '13 at 13:39
  • 3
    @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). –  Dec 10 '13 at 13:42
  • @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`. – lhf Dec 10 '13 at 13:50
  • @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. – Max Kielland Dec 10 '13 at 13:51
  • 4
    @MaxKielland, I'm afraid you'll have to change your design or place the definition of `onData` in a separate chunk. – lhf Dec 10 '13 at 13:52
  • @lhf 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... – Max Kielland Dec 10 '13 at 13:58
  • 1
    @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. – greatwolf Dec 11 '13 at 00:17
  • @greatwolf 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... – Max Kielland Dec 11 '13 at 07:59