Rick Posted September 25, 2011 Share Posted September 25, 2011 Does anyone know the Lua code in that is used to call engine Lua functions from say the editor? I'm using the following but the editor gives me access violation: lua_getglobal(L, "LuaFunctionName"); lua_pcall(L, 0, 0, 0); If Josh is able to show how say the editor is calling lua function from C++ or BMax that should help. Quote Link to comment Share on other sites More sharing options...
Rick Posted September 26, 2011 Author Share Posted September 26, 2011 I can't figure out why this isn't working: int state = lua_type(L, -1); Is telling me a function (the one I push) is on the stack, but any call to it (lua_pcall(L, 0, 0, 0) gives the Editor the ACCESS VIOLATION error. The fact that getglobal seems to be finding the function seems good, but not sure what else the call is expecting to make the editor crash. Also, those ACCESS VIOLATION errors I assume is from a lack of error handling so would be nice if we had more graceful error checking around Lua. Quote Link to comment Share on other sites More sharing options...
Josh Posted September 26, 2011 Share Posted September 26, 2011 Local size:Int size=luastate.StackSize() lua_getglobal(luastate.L,"UpdatePhysicsHook") If lua_isfunction(luastate.L,-1) luastate.PushObject(Self) luastate.invoke(1,0) EndIf luastate.SetStackSize(size) Method StackSize:Int() Return lua_gettop(L) EndMethod Method SetStackSize(size:Int) {hidden} Local currentsize:Int=StackSize() If size<currentsize lua_pop(L,currentsize-size) EndIf EndMethod Method Invoke:Int(in:Int=0,out:Int=0) Local error:String Local result:Int Local time:Int Local dummy:Object Local debugmode:Int ?debug debugmode=True ? If debugmode result=lua_pcall(L,in,out,0) Else Try result=lua_pcall(L,in,out,0) Catch dummy:Object HandleException() EndTry EndIf If result HandleError() Return False EndIf If autogc If CollectGarbageFrequency>0 time=MilliSecs() If time-lastcollectgarbagetime>CollectGarbageFrequency lastcollectgarbagetime=time ' CollectGarbage() EndIf EndIf EndIf Return True EndMethod Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted September 26, 2011 Author Share Posted September 26, 2011 Thanks for that. Still gives me the error. If I misspell the function name it fails the is_function call so I know it's finding the function, and pushing it on the stack but it just fails when calling. This is Lua 5.1 right? I'm currently using the binaries so I guess I'll get the source and use that in my project so I can step through the pcall method and see if I can get any more details around the error. It seems odd that the error would be coming from the editor and not my DLL though. The editor is single threaded right? I mean while I'm in my DLL making lua calls nothing should be happening on the Lua side of the editor calling model scripts right? It's erroring internally to Lua at: void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (; { const Instruction i = *pc++; // access violation error here Of course I have no idea of the internal workings of Lua but pc doesn't seem to be null or 0. It has what seems to be a valid address but when this tries to increase it, the failure happens. I wouldn't think it would be any sort of cross process issue as I thought the lua_State was meant to be self contained and passed around at will. Quote Link to comment Share on other sites More sharing options...
Rick Posted September 26, 2011 Author Share Posted September 26, 2011 So Josh you are using 5.1 right? Nothing special modified of the Lua version that you are using? This all works fine if lua.exe (the binary you can download of lua) is running my script, so it almost leads me to believe that it's the implementation of Lua in the editor and any slight Lua modifications that may have been made (to the Lua library itself)? There was another strange quirk I noticed where getting the first thing on the stack of a function call wasn't the first argument but a function, which wasn't the case in lua.exe when running a test script. I think at one point you gave me the person who did this implementation of Lua for you. Would that person still be associated with LE and would I be able to ask that person a question around this? Or if you know of any Lua change would you happen to have the changed Lua library that I could use in my C++ program? It just seems like this is something specific to the engine's version of Lua. Going to give Engine.exe to see if that gives the same results. Never used Engine.exe before so will have to see how that works. Quote Link to comment Share on other sites More sharing options...
Rick Posted September 27, 2011 Author Share Posted September 27, 2011 Looks like the same thing happens in Engine.exe. Guess I'll try creating my own exe that does this and see if that works. While I'm stepping through running this via Editor/Engine vs the lua.exe I'm able to see the variable that is messed up. I just don't know why it's messed up. It seems to be the lua_State variable is slightly different when ran from Editor/Engine vs lua.exe. It just makes no sense how you can call that method and it works, but when I call it, it doesn't. The lua_State variable must lose something when it gets xfered to my DLL, but why wouldn't it do the same from lua.exe. Frustrating as this is the last piece of getting RakNet working in Lua and me getting multiplayer in my game. I guess tonight I'll try returning network message and bitstream from the Update and handle the function mapping on the Lua side. Should give the same result. Quote Link to comment Share on other sites More sharing options...
AndyGFX Posted September 27, 2011 Share Posted September 27, 2011 Hi Rick i never tried put loop inside lua execute function, i think this isn't good. In my code i have luaV_execute defined as separated exec for external lua function and in native code when i call OnUpdate loop on any object (i.e. gui element) i call this external lua function in loop. From my point of view, your partly published code, look like recursive call => stack overflow or crash. When you want look on my implementation (but in Delphi) you look here: http://sites.google.com/site/andygfxproject/free-pascal/final3d-sdl-ngine source are on bottom of page. Note: Yes I'm always around here, but now i work more for mobiles and Tablets with Monkey. Quote [HW] C2D Q6600, 4GB RAM, NV8800GTX, Vista Ultimate x64 [sW] Blide Plus, BlitzMax, Delphi, C++, 3DWS 5.53, Leadwerks 2.xx Link to comment Share on other sites More sharing options...
Rick Posted September 27, 2011 Author Share Posted September 27, 2011 Hey Andy, I'm actually not looping in the lua execute function that I listed. That's how Lua has that method define as is part of the Lua API. I didn't touch it, was just showing where the error was happening inside Lua. What I actually do in my DLL is that I have an Update method that is exposed to Lua. In the main game loop in Lua I call this Update method. The Update method is looking for packets over the network via RakNet and if it finds one it notes the message id, and finds the lua function name I've registered to that ID which is stored in the DLL. Then it attempts to call that. It's strange because this all works great from lua.exe (prebuilt lua interpreter you can download). It's only when I try it from LE's lua when I get the error. The other thing that's strange is that the first parameter of a C function called from Lua is not the real first parameter I've passed in from Lua when using LE, but it is when called from lua.exe which loads a lua file and runs it. In LE I have to start with index 2 instead of 1 when looking at the first parameter. That tells me something strange is going on with LE's implementation of Lua. I think the editor is built using BMax, and engine might be also, so maybe the BMax version of Lua isn't exactly the same as the C version? Not sure. Tonight I'm going to try and just return the message id, and the data inside that message from the Update method and I'll just do the function mapping on the Lua side. It's not ideal in my mind but it should work. The link that you posted, that's not LE though right? That's SDL? Are you using prebuilt lua library and DLL as the interpreter or is there a Delphi port of Lua? Quote Link to comment Share on other sites More sharing options...
Rick Posted September 27, 2011 Author Share Posted September 27, 2011 Man I can't get a value returned to Lua from the DLL either to do this the other way I was thinking. I know this used to work as I'm looking at my example from the old forum. I was so close to getting this thing online, but now it's looking like I'm going to have to rewrite it in C++. static int NetUpdate(lua_State* L) { RakNet::MessageID msg = -1; RakNet::BitStream* reader = NULL; // check for new packets for (packet=peer->Receive(); packet; peer->DeallocatePacket(packet), packet=peer->Receive()) { // assign the message msg = packet->data[0]; // assign the bitstream reader = new RakNet::BitStream(packet->data,packet->length,false); reader->IgnoreBytes(sizeof(RakNet::MessageID)); // special case for connection. need to save off the servers address so we can send data to it later switch(packet->data[0]) { case ID_CONNECTION_REQUEST_ACCEPTED: WriteLog("Connection request accepted"); serverAddress = packet->systemAddress; break; } } // hardcode just to test lua_pushnumber(L, 5); return 1; } package.loadlib("C:\\Leadwerks Engine SDK\\RakNetLua.dll", "luaopen_raknet")() local msgID = raknet.Update() Notify(msgID) Just prints out nothing (nil) Quote Link to comment Share on other sites More sharing options...
AndyGFX Posted September 28, 2011 Share Posted September 28, 2011 This is very strange because i have used same method to return value from native code to lua script. Try add check inside C code if it's really function pointer returned from lua stack. state = lua_type(L,-1); state constants are: LUA_TNIL = 0; LUA_TBOOLEAN = 1; LUA_TLIGHTUSERDATA = 2; LUA_TNUMBER = 3; LUA_TSTRING = 4; LUA_TTABLE = 5; LUA_TFUNCTION = 6; LUA_TUSERDATA = 7; LUA_TTHREAD = 8; Quote [HW] C2D Q6600, 4GB RAM, NV8800GTX, Vista Ultimate x64 [sW] Blide Plus, BlitzMax, Delphi, C++, 3DWS 5.53, Leadwerks 2.xx Link to comment Share on other sites More sharing options...
Rick Posted September 28, 2011 Author Share Posted September 28, 2011 I will give this a try tonight This is very strange because i have used same method to return value from native code to lua script. With LE and Lua or with some other implementation of Lua outside of LE. If withing LE I'd love to see what code you have for that. What exact version of Lua (patch version also) and a working example if you have one because this all works when done from lua.exe but not when done from LE as the host of Lua. Quote Link to comment Share on other sites More sharing options...
AndyGFX Posted September 28, 2011 Share Posted September 28, 2011 WHen you want see how work my code, you can download it here: https://sites.google.com/site/andygfxproject/free-pascal/final3d-sdl-ngine/Final3D_SDL_nGine.rar?attredirects=0&d=1 Run: F3D_DEMO_scene_render.exe and press F1 or F3D_DEMO_gui_with_lua.exe - GUI has used call function from native code. LUAfile: ..\Final3D_SDL_nGine\bin\data\scripts\editor\editor_gui.lua ... GUI.SetHSlider_OnChange("WIN_01","HSlider_01","fnc_Hslider_onchange"); ... and fnc is defined: function fnc_Hslider_onchange() local val = GUI.GetHSliderValue("WIN_01","HSlider_01"); print(val); end; and now GUI.GetHSliderValue in native code: wF3D_GUI.pas F3D.ScriptEngine.AddListFunction('GetHSliderValue', @lua_GUI_HSlider_GetValue); function lua_GUI_HSlider_GetValue(L: lua_state): integer; cdecl; var w_name: string; i_name: string; w_id, i_id: integer; begin w_name := lua.luaL_check_string(L, 1); i_name := lua.luaL_check_string(L, 2); w_id := F3D.GUI.FindWindowByName(w_name); if w_id >= 0 then begin i_id := F3D.GUI.Window[w_id].FindHSliderByName(i_name); if i_id >= 0 then begin lua.lua_pushnumber(L, F3D.GUI.Window[w_id].HSlider[i_id].value); end; end; result := 1; end; Maybe your function isnt properly defined. I have used this steps 1) F3D.ScriptEngine.StartList('GUI'); procedure TF3D_ScriptEngine.StartList(name: pchar); begin if (self.enabled = false) then exit; lua_pushstring(VM, name); lua_newtable(VM); end; 2) Add functions to GUI table; ... // HSLIDER F3D.ScriptEngine.AddListFunction('SetHSlider_OnChange', @lua_GUI_HSlider_OnChange); F3D.ScriptEngine.AddListFunction('GetHSliderValue', @lua_GUI_HSlider_GetValue); ... procedure TF3D_ScriptEngine.AddFunction(name: pchar; fnc: pointer); begin if (self.enabled = false) then exit; lua_pushstring(VM, name); lua_pushcclosure(VM, fnc, 0); lua_settable(VM, LUA_GLOBALSINDEX); end; 3) F3D.ScriptEngine.EndList(); (F3D_ScriptEngine.pas) procedure TF3D_ScriptEngine.EndList(); begin if (self.enabled = false) then exit; lua_settable(VM, LUA_GLOBALSINDEX); end; I have used Lua 5.1 and bum dll, for linux was used lua.so Quote [HW] C2D Q6600, 4GB RAM, NV8800GTX, Vista Ultimate x64 [sW] Blide Plus, BlitzMax, Delphi, C++, 3DWS 5.53, Leadwerks 2.xx Link to comment Share on other sites More sharing options...
Josh Posted September 28, 2011 Share Posted September 28, 2011 It's using LuaJIT 1.1.6, but I don't know if that makes any difference. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted September 28, 2011 Author Share Posted September 28, 2011 @Andy but that's using SDL and not LE right? So the Lua implementation might be different. Like I was saying it works all fine with Lua.exe only when using with LE. @Josh, hmm that might be it. I don't know anything about LuaJIT, but perhaps it does some things slightly different. So LuaJIT is a complete replacement from just normal Lua? I bet this it though because I remember not having these issues when you first introduced Lua and I seem to remember you switched over to LuaJIT some time after. I'll use LuaJIT in my DLL and see if that makes the difference. If so, we'll have to really specify it uses LuaJIT instead of just Lua because then clearly there would be some slight differences. Quote Link to comment Share on other sites More sharing options...
Rick Posted September 29, 2011 Author Share Posted September 29, 2011 Well that was it! I thought I was going crazy. Thanks Josh for pointing this out. I forgot that you switched to that. Thanks Andy and everyone else who helped. All working nicely now. Asking over at RakNet if he minds me giving my custom DLL away as it still requires the RakNet dll to work and people would still have to go through him to get that. This might be useful for others and it's really simple to use. This is just for client stuff via Lua though, the server would still be pure RakNet (ie. in C++ or .NET or whatever supported RakNet language you want to use). Quote Link to comment Share on other sites More sharing options...
Gabriel Posted November 4, 2011 Share Posted November 4, 2011 Man I can't get a value returned to Lua from the DLL either to do this the other way I was thinking. I know this used to work as I'm looking at my example from the old forum. I was so close to getting this thing online, but now it's looking like I'm going to have to rewrite it in C++. static int NetUpdate(lua_State* L) { RakNet::MessageID msg = -1; RakNet::BitStream* reader = NULL; // check for new packets for (packet=peer->Receive(); packet; peer->DeallocatePacket(packet), packet=peer->Receive()) { // assign the message msg = packet->data[0]; // assign the bitstream reader = new RakNet::BitStream(packet->data,packet->length,false); reader->IgnoreBytes(sizeof(RakNet::MessageID)); // special case for connection. need to save off the servers address so we can send data to it later switch(packet->data[0]) { case ID_CONNECTION_REQUEST_ACCEPTED: WriteLog("Connection request accepted"); serverAddress = packet->systemAddress; break; } } // hardcode just to test lua_pushnumber(L, 5); return 1; } package.loadlib("C:\\Leadwerks Engine SDK\\RakNetLua.dll", "luaopen_raknet")() local msgID = raknet.Update() Notify(msgID) Just prints out nothing (nil) try with static int _cdecl NetUpdate(lua_State* L) { ... } May be that the name convention is not recognized by Lua! In "C + +" all are decorated like @@foo(ZER_@) but not in "C" Can you tell me if it works like that? I'm interested;-) Gabriel Quote Link to comment Share on other sites More sharing options...
Rick Posted November 4, 2011 Author Share Posted November 4, 2011 I got this working. My last post shows what the issue was. Josh is using LuaJIT and I was using pure Lua. There are slight differences in the lua_State variable between the 2 so mixing them doesn't work. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.