Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Due to spam on this forum, all posts now need moderator approval.
Entire forum
➜ Programming
➜ General
➜ Imbedding Lua in your own applications
Imbedding Lua in your own applications
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Fri 24 Mar 2006 03:46 AM (UTC) Amended on Fri 24 Mar 2006 03:47 AM (UTC) by Nick Gammon
|
Message
| This material is covered in the Lua documentation, but I will do my own version here to help people who are relying on this site for Lua information. :)
Let's start with a simple C program that creates a Lua "script space" and runs a simple literal script:
#include "lua.h"
const char * myscript =
" print ('Hello, world. Lua version is', _VERSION)";
int main (void)
{
lua_State * L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
luaL_loadbuffer (L, myscript, strlen (myscript), "example"); /* compile */
lua_pcall (L, 0, 0, 0); /* execute */
lua_close (L); /* close Lua */
return 0;
} /* end of main */
This has the absolute basics. It:
- Creates a script space (in the variable L)
- Adds to it the basic library functions (such as 'print')
- Compiles the script (with luaL_loadbuffer)
- Executes the script (with lua_pcall)
- Closes the script space
- Exits
I needed the lua.h file from the Lua distribution, and the lua50.lib file from the Windows binary distribution. The file lua50.dll also needs to be somewhere in your path.
I compiled it like this (under Cygwin):
gcc test.c lua50.lib -o test.exe
This compiled test.c (the above file) and linked in the lua50.lib library. Then running it gives the expected results:
Hello, world. Lua version is Lua 5.0.2
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #1 on Fri 24 Mar 2006 03:56 AM (UTC) |
Message
| One major problem with the above example is that there is no error handling. If the script has errors you won't know about them, it will silently fail. This more elaborate example will detect and display any compile or runtime error:
#include <stdio.h>
#include "lua.h"
const char * myscript = " print ('Hello, world. Lua version is', _VERSION)";
int main (void)
{
int error;
lua_State * L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
error =
luaL_loadbuffer (L, myscript, strlen (myscript), "example") ||
lua_pcall (L, 0, 0, 0);
if (error)
{
fprintf (stderr, "%s", lua_tostring (L, -1));
lua_pop (L, 1);
}
lua_close (L);
return 0;
} /* end of main */
If either the call to compile, or execute, fails it returns a non-zero value, and the error message is left on top of the Lua stack, which can be obtained by calling lua_tostring.
This example simply displays the message, although obviously you could put it into a dialog box, echo it to your user, or whatever is appropriate.
Let's test that with different scripts. If the script is:
const char * myscript = " print (2 'nick') ";
Then I see:
[string "example"]:1: `)' expected near `'nick''
That was a compile-time error. However if I make a runtime error (adding a number to a string, then you get a different message:
const char * myscript = " print (2 + 'nick') ";
This gives:
[string "example"]:1: attempt to perform arithmetic on a string value
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #2 on Fri 24 Mar 2006 04:22 AM (UTC) |
Message
| Now let's try a more elaborate example. This one will read in a file (an obvious example here is to read a configuration file for a program). The file is loaded and compiled, then executed, effectively putting any assignments it does into the Lua script space.
My example Lua file is this:
a = 22
b = 33
c = "nick"
-- do tests if wanted
if a < b then
a = 99
end -- if
The advantage of using Lua is that you can do tests or arithmetic inside the configuration file (and put comments).
Here is the code to read it in. We also extract a couple of values from the Lua script space back into C space:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "lua.h"
void error (lua_State *L, const char *fmt, ...)
{
va_list argp;
va_start (argp, fmt);
vfprintf (stderr, fmt, argp);
va_end (argp);
lua_close (L);
exit (1);
} /* end of error function */
int main (void)
{
int a, b;
const char * c;
lua_State * L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
if (luaL_loadfile(L, "myconfig.lua") ||
lua_pcall (L, 0, 0, 0))
error (L, "Error loading file: %s", lua_tostring (L, -1));
/* get value of "a" */
lua_getglobal (L, "a");
if (!lua_isnumber (L, -1))
error (L, "'a' should be a number\n");
a = (int) lua_tonumber (L, -1);
printf ("Found value of 'a' to be %i\n", a);
lua_pop (L, 1);
/* get value of "c" */
lua_getglobal (L, "c");
if (!lua_isstring (L, -1))
error (L, "'c' should be a string\n");
c = lua_tostring (L, -1);
printf ("Found value of 'c' to be %s\n", c);
lua_pop (L, 1);
lua_close (L);
return 0;
} /* end of main */
This example also uses a more elaborate error function (suggested from the Lua book). This error function reports the error and terminates the application, however you may find it more useful to report the error to the user and continue processing. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #3 on Fri 24 Mar 2006 04:24 AM (UTC) |
Message
| The above example uses the Lua API functions to extract numbers and strings from the global address space. An obvious enhancement for a bigger application would be to make that extraction into a small function (one for numbers, one for strings, and so on). You might also handle defaults by testing for nil, and if so substituting some default value. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #4 on Fri 24 Mar 2006 04:29 AM (UTC) |
Message
| Now let's look at adding in the normal Lua libraries. This simply involves a few more lines of initialization code:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "lua.h"
void error (lua_State *L, const char *fmt, ...)
{
va_list argp;
va_start (argp, fmt);
vfprintf (stderr, fmt, argp);
va_end (argp);
lua_close (L);
exit (1);
} /* end of error function */
int main (void)
{
lua_State * L = lua_open(); /* opens Lua */
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */
luaopen_loadlib(L); /* loadlib function */
luaopen_debug(L); /* debug library */
if (luaL_loadfile(L, "myconfig.lua") ||
lua_pcall (L, 0, 0, 0))
error (L, "Error loading file: %s", lua_tostring (L, -1));
lua_close (L);
return 0;
} /* end of main */
Running this on this file:
for i = 1, 10 do
print (i, math.sqrt (i))
end -- if
... gives:
1 1
2 1.4142135623731
3 1.7320508075689
4 2
5 2.2360679774998
6 2.4494897427832
7 2.6457513110646
8 2.8284271247462
9 3
10 3.1622776601684
Note in this example we have used a function in the math library.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #5 on Fri 24 Mar 2006 05:00 AM (UTC) |
Message
| If you decide to use Lua 5.1 (rather than 5.0.2) then opening the libraries is simpler, and indeed required to be done this simpler way or it crashes:
#define _WIN32
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
void error (lua_State *L, const char *fmt, ...)
{
va_list argp;
va_start (argp, fmt);
vfprintf (stderr, fmt, argp);
va_end (argp);
lua_close (L);
exit (1);
} /* end of error function */
int main (void)
{
lua_State * L = luaL_newstate (); /* opens Lua */
luaL_openlibs (L); /* new way of opening all libraries */
if (luaL_loadfile(L, "myconfig.lua") ||
lua_pcall (L, 0, 0, 0))
error (L, "Error loading file: %s", lua_tostring (L, -1));
lua_close (L);
return 0;
} /* end of main */
The main change is that the multiple lines which opened the libraries are replaced by a single line (luaL_openlibs) which opens all of the standard libraries for you.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Dralnu
USA (277 posts) Bio
|
Date
| Reply #6 on Fri 24 Mar 2006 08:35 AM (UTC) |
Message
| Great timing Nick. I needed something to use for a guide, and I think this may help get me on my way, plus I know alot of others will love to have the info | Top |
|
Posted by
| Zeno
USA (2,871 posts) Bio
|
Date
| Reply #7 on Fri 24 Mar 2006 11:01 AM (UTC) Amended on Fri 24 Mar 2006 11:19 AM (UTC) by Zeno
|
Message
| This is odd.
Nick, in your latest post (the one before Dralnu's) the time of the post is not shown. A bug?
Anyways. I am considering imbedding Lua into Project CR, but I don't see where I would use it. Hm. |
Zeno McDohl,
Owner of Bleached InuYasha Galaxy
http://www.biyg.org | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #8 on Fri 24 Mar 2006 12:49 PM (UTC) |
Message
| The time shows up for me. It's at 10:00 PM. Maybe if you're in Central Time, or whatever is Pacific+2, it's exactly midnight, which confuses something?
For your project, I'd consider using Lua as a data storage mechanism. And then you can use it as a replacement for mudprog. Lua would excel in both areas. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Zeno
USA (2,871 posts) Bio
|
Date
| Reply #9 on Fri 24 Mar 2006 02:30 PM (UTC) |
Message
| You're right, it's my time zone. It shows up when I'm not logged in. I guess it has issues displaying if it's 0?
Well I won't have any mudprogs. Data storage? As in maybe player files, game options etc? |
Zeno McDohl,
Owner of Bleached InuYasha Galaxy
http://www.biyg.org | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #10 on Fri 24 Mar 2006 04:38 PM (UTC) |
Message
|
Quote: As in maybe player files, game options etc? Precisely. These are really just key-value pairs, i.e. "min_level_avatar" = 51 in SMAUG.
In Lua, you can set up your settings as a table, and then use serialization classes (Nick wrote an example around here somewhere) to output the table to a Lua script. Then the next time you need to load the data, you just load the script, and in doing so you will have loaded up tables to say what exactly has been done. :) |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #11 on Fri 24 Mar 2006 09:49 PM (UTC) |
Message
| Yes, Lua would really lend itself to reading in those sorts of things. Examples would be:
- MUD configuration (eg. name, port number, welcome message)
- Player files
- Classes, races, spells
- Areas
The beauty of Lua is that you basically load in the entire file in one line of code. If you decide to change the files later the loading code doesn't have to be changed. Also the files can be complex (eg. spells might contain multiple effects, which can be in a table, players might have inventory which contain bags which contain potions - these can be tables of tables). |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
46,302 views.
It is now over 60 days since the last post. This thread is closed.
Refresh page
top