Jump to content

Lua version in 3.0


Rick
 Share

Recommended Posts

You can just start using the C++ Lua command set right away in any Leadwerks C++ project, with no extra work. You don't need to worry about which platforms use Lua and which use LuaJIT, it will all just work.

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

It doesn't for me. What do I need to include for a header? I included "Leadwerks.h" and the following give me linker errors saying the functions don't exist.

 

lua_getglobal(Interpreter::L, luaHandlers[msg].c_str());
lua_pushlightuserdata(Interpreter::L, &reader);
lua_pcall(Interpreter::L, 1, 0, 0);

 

1>lua-gluecode.obj : error LNK2019: unresolved external symbol "int __cdecl lua_gettop(struct lua_State *)" (?lua_gettop@@YAHPAUlua_State@@@Z) referenced in function "int __cdecl tolua_luacommands_RakNetNetwork_new00_local(struct lua_State *)" (?tolua_luacommands_RakNetNetwork_new00_local@@YAHPAUlua_State@@@Z)
1>RakNetNetwork.obj : error LNK2019: unresolved external symbol "int __cdecl lua_pcall(struct lua_State *,int,int,int)" (?lua_pcall@@YAHPAUlua_State@@HHH@Z) referenced in function "public: void __thiscall RakNetNetwork::Update(void)" (?Update@RakNetNetwork@@QAEXXZ)
1>RakNetNetwork.obj : error LNK2019: unresolved external symbol "void __cdecl lua_pushlightuserdata(struct lua_State *,void *)" (?lua_pushlightuserdata@@YAXPAUlua_State@@PAX@Z) referenced in function "public: void __thiscall RakNetNetwork::Update(void)" (?Update@RakNetNetwork@@QAEXXZ)
1>RakNetNetwork.obj : error LNK2019: unresolved external symbol "void __cdecl lua_getfield(struct lua_State *,int,char const *)" (?lua_getfield@@YAXPAUlua_State@@HPBD@Z) referenced in function "public: void __thiscall RakNetNetwork::Update(void)" (?Update@RakNetNetwork@@QAEXXZ)
1>C:\Leadwerks\Projects\Duck\Projects\Windows\..\..\\Duck.debug.exe : fatal error LNK1120: 4 unresolved externals

 

ws2_32.lib

OpenGL32.lib

Glu32.lib

winmm.lib

Psapi.lib

 

These are the only libs you have in the project so the actual lua functions don't exist anywhere.

Link to comment
Share on other sites

You can call PushObject() for any class derived from a Leadwerks Object. Note the object needs a function like this so Lua knows what it is:

std::string Sound::GetClassName()//don't forget to make this virtual!!!
{
	return "Sound";
}

 

This is the source for Object::Push():

	void Object::Push(const bool takeownership)
{
	if (Interpreter::L==NULL) Interpreter::Reset();
	if (takeownership)
	{
		tolua_pushusertype_and_takeownership(Interpreter::L,(void*)this,GetClassName().c_str());
	}
	else
	{
		tolua_pushusertype(Interpreter::L,(void*)this,GetClassName().c_str());
	}
}

 

 

Link to comment
Share on other sites

Well I screwed something up. Now App.lua is saying it can't find a script that it was finding before I started screwing around adding RakNet and using tolua++.

 

Erroring on: require "Scripts/States/StateManager.lua" even though it does exist. Any ideas?

Link to comment
Share on other sites

I didn't use the BMX file. I have no idea how to run a BMX app, but I'm not really interesting in messing with that right now. I only have 2 headers so I just manually copied and pasted to the pkg file.

 

So I added the dofile and rquire declarations in the package and just changed to referenced Leadwerks version of these in the generated code. ie. replace dofile() with Leadwerks::dofile().

 

After adding the dofile() and require() it gets passed the !Interpreter::ExecuteFile("Scripts/App.lua") fine now, but hits false on:

 

if (!Interpreter::Invoke(1,1,errorfunctionindex)) return false;

 

I get error: "Lua Error error in error handling" and the program quits.

 

 

So I think for sure we need to have the dofile and require code at the end of our package and need to replace it with Leadwerks:: versions in the generated code, because that makes it do ExecuteFile() works (since the Lua files use dofile and require), but now we have this errorfunctionidex issue.

 

 

So not sure what's up with that error function invoking error.

Link to comment
Share on other sites

When Lua hits an error, the C++ program doesn't know about it until the script is finished executing. In order to pause the program and display the call stack in the debugger, a hook is required that will connect to the Leadwerks debugger and send the call stack over. Lua allows this by providing it with an error function to call if something goes wrong.

 

If you only have a couple of header files, it's much easier to do them manually like your are.

 

 

Link to comment
Share on other sites

What/where is this error function then? Is it a lua function or C++ function? Right now it's hitting this error function and returning false in App:Start() in C++ so I'm dead in the water right now on my next debugging steps to see why this isn't working.

 

Since it's returning false on: if (!Interpreter::Invoke(1,1,errorfunctionindex)) return false;

 

I assume this means it can't find the error function to call? Why would that be? At this point in the code I haven't even done any of my own stuff.

Link to comment
Share on other sites

The function LuaErrorHandler can be found in Error.lua:

function LuaErrorHandler(message)
   Debug:Error("Lua Error: "..message)
end

 

This just calls the C++ function Debug::Error(), which connects to the debugger and pauses the program.

 

This script is automatically run when Lua is initialized.

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

OK, so the good news is it's making it inside this function because the error I get is: "Lua Error: error in error handling" which is clearly coming from this error handler because it starts with "Lua Error: ". However the message "error in error handling" isn't all that descriptive smile.png.

 

If it seems like it's getting inside this function why would: Interpreter::Invoke(1,1,errorfunctionindex) be returning false making the application quit when being done in:

 

if (!Interpreter::Invoke(1,1,errorfunctionindex)) return false;

 

It would seem to me it was able to invoke the error handler function since I get the error msgbox from it, so why would it return false? What's going on inside Interpreter::Invoke() that's making it return false?

Link to comment
Share on other sites

Attached is the pkg file that has the 2 headers for my classes. After it's created I just manually add the includes, but then I also had to make the calls to lua's dofile/require be Leadwerks::dofile/require. I also have to change the lua get_top which I assume is equal to Leadwerks::Interpreter::GetStackSize().

 

After I make those changes the project compiles, but then I get the error function being called when it tries to Invoke the App:Start() function.

 

 

Side Note: I find that if I exclude the tolua generated cpp file everything works. So the existence of that file in the project is causing issues even though I get the error BEFORE I even call anything generated in that file. The simple fact that it's in the project causes the problem.

luacommands.rar

Link to comment
Share on other sites

OK, I was able to get it to run by renaming a couple functions in the file.

 

I renamed tolua_luacommands_open to tolua_luacommands_open1 and

luaopen_luacommands to luaopen_luacommands1.

 

Here is what I'm thinking. You used this same method of getting your Leadwerks objects and so those 2 functions are the exact same name for the tolua code you generated. Then when I add it into the project we now have 2 sets of the same function names! I'm shocked it even compiled like that but it does, but clearly that's screwing stuff up.

 

I don't know how I can call my new tolua_luacommands_open1() function inside App.cpp thought? Since it's a cpp file I can't include any header file that tells App.cpp that function exists so it can't find it.

Link to comment
Share on other sites

Sorry for the stream of thought, but I think I got it working. I took out the declaration to tolua_luacommands_open1() from the cpp file and made a header file that looks like:

 

#pragma once

#include "Leadwerks.h"

#include "tolua++.h"

/* Exported function */
TOLUA_API int tolua_luacommands_open1(lua_State* tolua_S);

 

I then include this header file in the tolua generated cpp file AND app.cpp so that I can call tolua_luacommands_open1() in App:Start() in App.cpp.

 

 

I don't get errors now when trying to call my classes from Lua and it's hitting breakpoints in my VS project for my class when I make the call from Lua! Success!!!!

 

I would say this is far from how easy you made it sound on this page smile.png

 

http://www.leadwerks.com/werkspace/files/file/216-tolua/

 

 

If everything works, I'll post a tutorial on all the steps I did.

Link to comment
Share on other sites

I did include Leadwerks.h because I needed to change some of the base lua commands to the Leadwerks ones, like lua_gettop to Leadwerks:GetStackSize(). Also because I added the dofile/require at the end of the file (not even sure I needed to) I needed to use the Leadwerks version of these.

 

Now I have to see if I can expose this in a dll. The nice thing is embedding RakNet into the main exe I think is required for mobile games because from what I've read you can't really have dll/external libraries on mobile devices. However, if you do what you talked about on Steam then I would need a dll to hold the RakNet commands and load the dll via lua. I hope that works because then this will be able to run in all environments.

 

 

I just did an #include "Leadwerks.h" at the top, I didn't actually include all the contents of Leadwerks.h in the pkg so it wouldn't have regenerated any Leadwerks stuff.

Link to comment
Share on other sites

Josh, are you passing lua table functions back to c++ to be callbacks at all? If so, how are you doing it?

 

 

So I'm looking at how you do App stuff. Looks like you create a table from C++ and call it App. Then you load the App.lua file which defines the Start() & Loop() functions. Then you get the App table, get the Start function, push the app table as self, and call the Start function.

 

The main difference in my situation is that the table isn't created in C++, but created in lua. I would have to pass the table to my C++ function. I don't think I could really give it a name with SetGlobal. It must have a name already when it's created from lua that I can use?

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...