출처 : http://www.codegurus.be/codegurus/Programming/luaintroduction_en.htm

 

 

Using LUA with Visual C++ (Introduction)

What is LUA?

LUA is a scripting language, its power lies in the fact that it can be embedded in your C++ programs.  Scripts give you the possibility to change the behaviour of your C++ programs without any need to recompile your program.  A real world example would be game programming: you only have to change the script(s) and you can create a whole new game using the same engine.

LUA is fully customizable, you can create your own script functions and expose them to a 3th party.  Or you can create scripts, encrypt them and then decrypt them at run-time so that only a number of limited people can script for your program.  Allowing the end-user to modify your program, gives your program a point ahead to the competition.

Using LUA in your program does require some thinking ahead...  You have to choose what kind of functions you allow in the scripts.  For example: a function savegame would be logic and usefull and so could be a function deletesavegame but making a function such as deletefile public can be dangerous.

The LUA version discussed is 5.0.2.  Don't forget that this document is only a quick introduction and that it is not a complete tutorial about LUA.
 

How to embed LAU into C++?

Another way to formulate this question : "How can I use LUA in my Visual C++ Project?".  The answer is actually pretty easy, you download it from lua.org and you follow the instructions below.  Know that there are several ways to add LUA to your project and I only explain one of them.

NOTE: I'm assuming that you know the basics about how to use your compiler, the instructions outlined below are ment for Microsoft Visual C++ 6.

Installation :

  1. dowload LUA here (links to official website)
  2. Extract the files to a folder, for example "c:\Program Files\LUA SDK"

Configuration :

  1. In your Microsoft Visual C++ IDE Go to Tools->Options.
  2. Select Directories and add the LUA include-directory.

Add LUA to your project (non-MFC) :

  1. Create a new folder in your project's workspace and call it LUA.

  2. Add the files.

  3. Select and insert all the files in the LUA src-directory (from lapi.c to lzio.h).

Add LUA to your project (MFC) :

  1. Create a new folder in your project's workspace and call it LUA.

  2. Add the files.

  3. Select and insert all the files in the LUA src-directory (from lapi.c to lzio.h).

  4. MFC uses precompiled headers, LUA doesn't, so let's disable them.  Select the LUA folder in your workspace and press the right mouse button, then select Settings from the menu.

  5. Select "All Configurations".

  6. Then open the LUA folder and select all the .c-files (make sure your selection doesn't include a folder or a .h file!).  On the right side a C++-tab will appear.  In that C++-tab select the "Precompiled Headers"-catagory.  And select "Not using precompiled headers".  Press the OK-button to finish.

 

About ANSI C and C++

LUA is pure ANSI C code, this means that if you build the code with a C++ compiler it will complain with "error LNK2001: unresolved external symbol" messages.  Two easy ways exist to resolve this problem without modifying the original source files :

  1. Tell the compiler that the function definitions are C style by enclosing the include directive with the extern keyword :
  2. You can also define LUA_API before including lua.h :

I recommend that you use the first method.

 

The LUA State

In order to use LUA you have to initialize it and when you're done with it you have to deinitialize LUA.  This is done by respectivily opening and closing an LUA state.

You can have multiple LUA states in your program which are all indepedent of each other.

 

The LUA Stack

LUA is stack-based.  The communication between the script and the C/C++ application happens between a stack maintained by LUA.  Note that each LUA state has its own stack.  A clean programmer will ensure that the stack is zero at the end of his program.  You can verify this by calling the lua_gettop function, the result must be zero, it's a good candidate for the _ASSERT macro (defined in crtdbg.h).

LUA defines lua_pushXXX (where XXX can be "string", "number", "boolean", ...) but it doesn't define the lua_popXXX versions.  Here's an example how to define them by yourself :

When popping the values they are converted automaticly when possible :

If the conversion is impossible then NULL/0 will be returned.  For example we can't convert a boolean to a string :

There are many other stack manipulation functions and there are also functions to verify the value type on the stack.  I suggest that you check out the LUA manual that comes with the distribution.

 

Executing an LUA script

Executing an LUA script isn't that straight-forward at first but at the end it turns out the be very simple.  I'm explaining you the full implementation of how to execute a script by creating your own "reader".  LUA comes with its own library that contains ready-to-use functions but I prefer you to explain the complete version so you can understand better how LUA works.

In order to execute LUA scripts you have to load them first and call them afterwarts, this is done by respectivily calling the lua_load and the lua_call or lua_pcall function.

The lua_load function takes four parameters :

LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data, const char *chunkname);

The first one is the pointer to the LUA state, the second one is a pointer to a user-defined reader function, the third pointer is a user-defined value that the reader function will receive, and the fourth one is a name we decide ourselves for debugging purposes.  As you can see from this call, there is no argument accepting a script.  We have to define this ourselves using the data argument.  Let's take a look at this structure (taken from the LUA library), we will define :

The text variable will be our script line(s) and the size variable will tell us if we have finished reading or not (see later).  A value of zero will mean : we are no longer reading.  We now define a simple callback function :

Once the script has been loaded, a simple call to lua_pcall will suffice.  I prefer lua_pcall above lua_call because the later one will terminate the program if there was an error.

The lua_call takes three parameters and the lua_pcall function takes four parameters :

LUA_API void lua_call (lua_State *L, int nargs, int nresults);
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);

The first parameter is the pointer to the LUA state, the second parameter is the number of arguments on the stack that the command takes (and when executing a loaded script this can remain 0).  The third parameter is the number of result parameters the command will return on the stack.  If nresult equals LUA_MULTRET then the number of parameters that will be pushed on the stack is controlled by the called function!  Yes indeed, an LUA function can return more than one parameter, for example :



The fourth parameter (errfunc) is only valid for the lua_pcall function and is used for controlling the error-handling.  Please read the LUA manual for more information about this parameter.

A note about the nresults argument: if we take the example return statement above, then we see that 7 values would be returned.  If we execute this script with nresult==LUA_MULTRET then 7 values would be returned, if we would call the function with nresult==3 then only the 3 first values would be returned ("i", "return" and 5).

This is the test script we will execute :

 

A quick but nasty way of executing would be this :

You may ask why is this a bad method?  Well, there is no error checking, if the script contains error or an execution error occur than the stack will be messed-up, LUA functions push their error values on the stack so you need to check the result of both lua_load and lua_pcall and act accordingly!

This is the implementation that I prefer :

 

Calling C functions from LUA

In order to make this topic more accessible, a whole new page has been assigned to it, please follow this link : Calling C functions from LUA or How to expose C function to LUA scripts.

 

Download

You can download the above test project here (compressed ZIP files) :

The source code of LUA Demo 1
The executable version of LUA Demo 1

NOTE: All the required files are included in the source code file in order to compile succesfully

 

Contact

If you have questions or remarks about this article or its contents, then feel free to contact me at <fibergeek @ codegurus.be>.  Don't forget to remove the white spaces or the e-mail won't arrive.

 

External links

LUA: the official site

 

 

 

안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,