Posts Tagged ‘Lua C API’

Embedding Lua in C# .Net – Part III

February 21, 2011

This post contains a full managed lua wrapper around the lua API, a simple script engine making life easier when communicating with lua, a sample class ‘NPCPlayer’ to integrate with lua, a sample program using the script engine and the sample class and last a basic explanation of the lua stack.

Hopefully the post will fill in the gaps from part I and II and I will provide all the working source code to illustrate lua embedding.

Source code
All files referenced in this post can be downloaded as a zip file found here.
The source code contains lots of useful comments as well.

A full managed lua wrapper
The managed wrapper is defined in its completeness in the static class ‘Lua’
This class wraps all the lua c functions and constants, and bridges the integration to the natively compiled lua.dll.

The wrapper class can be found in the zip file in the introduction of the post.

A simple Script engine – how to use the managed wrapper
The wrapper is basically just a 1-1 bridging of the full lua API and constants.
To use it you will therefore need to understand how the various lua API functions work.

Most of the functions exposed through lua API operate on the lua stack.
To make life easier in communicating with lua through the stack, I have made a simple script engine class that has methods that encapsulates the lua API calls for some of the things you’ll often have to do.

This includes:

  • Instantiating lua and managing the lua state.
  • Error logging with messages from lua interpreter
  • Registering C# methods with lua
  • Creating a lua table
  • Getting and setting table fields
  • Pushing and popping values on the lua stack
  • Running a script file

The script engine class can be found in the zip file in the introduction of the post.

Demonstration application
I have made a small console app to demonstrate the use of the scriptengine together with a sample class ‘NPCPlayer’.
The app consists of a single class ‘Program’ in a single file.

The demonstration program class and the NPCPlayer class can be found in the zip file in the introduction of the post.

The lua stack
 
The single most important thing when extending your application with lua is to understand how the lua stack works, and how exactly you use it to communicate with lua.

Stack data structure
A stack data structure is a general structure used in many different languages to solve various computing problems.
If you do not know yet what a stack structure is and how it works, you should start by looking at an explanation here.

As you can see a stack data structure is kind of a tower of data elements stacked on top off each other.
When a new data element is put on top of the stack it is called a PUSH operation.
When the top element of the stack is removed, it is called a POP operation. 

PUSH and POP always operate from the top of the stack.
The stack is also called a LIFO structure (last in first out) because of how the operations on the stack function. 

An example
As a starting example I will explain the lua API function calls used in the script engines method ‘CreateLuaTable’
The lua stack will be empty after opening lua, and the ‘CreateLuaTable’ assumes an empty stack as well.

The method looks like this and takes a single string parameter containing the name of a lua table to create in lua.

public void CreateLuaTable(string tableName)
{
            Lua.lua_getglobal(m_lua_State, tableName);

            if (IsTopNil)
            {
                //remove the nil value
                Lua.lua_pop(m_lua_State, 1);
                Lua.lua_newtable(m_lua_State);
                Lua.lua_setglobal(m_lua_State, tableName);
                //stack is empty
            }
            else
            {
                //remove the existing table from the stack
                Lua.lua_pop(m_lua_State, 1);
            }
}

Explanation
First I use lua_getglobal to check if the table already exists.
Lua_getglobal PUSHES the lua table onto the lua stack if the table did exist, else it will leave the stack with a nil value on top.

I then check if the top of the lua stack is nil, if it is the table did not exist and I will create it.
I POP the nil value off the stack with lua_pop, that takes as argument how many elements to pop.

Stack is now again empty.

I then create a new lua table with lua_newtable which PUSHES the new lua table object onto the stack

A single table element is now sitting on top of the stack.

Then I set the name of the new table by using lua_setglobal which POPS the top element from the stack (must be a table element), while associating the identifier with it.

Stack is now again empty.

If at first the table did already exists, I make sure to balance the stack again properly in the else clause, by POPPING the found table object off the stack.
Either way the stack will look exactly as it did before entering the method.

This is the easiest way to ensure proper stack use.
There can be times though when it’s fitting to leave a table object on top of the stack when performing multiple operations on the same table, instead of constantly PUSHING and POPPING it on and off the stack.

It’s critical to know exactly how each lua API function will treat the stack when it is called.
How many arguments and their types will it assume on the stack when called?
How many elements will be left on the stack when the function is done?

You will have to look this behavior up in the lua documentation, until you get familiar with it.

Conclusion 
This ends part III of Embedding Lua in C# .Net
I hope you will find the post and the code snippets useful.

Thue Tuxen

Embedding Lua in C# .Net – Part II

January 7, 2010

Using Lua with .Net C# part II 

In the previous post I showed how the Lua source code can be built for use by .Net, and how to make a very simple hello Lua script, and execute it from .Net code. 

Putting Lua to real use 
To actually do something interesting Lua must be able to call into .Net functions that is registered with Lua. 

 This enables all sorts of exciting features, such as exposing your business / game objects to Lua and create Lua scripts for AI, custom business processing etc. 

.Net function signature for Lua callbacks 
Every .Net function that Lua should be able to call must match a specific function signature, and must also be registered with Lua. 

This is how the function signature should look in .Net: 

/*  definition from lua.h source code file
 *  typedef int (*lua_CFunction) (lua_State *L);
 */
public delegate int LuaFunction(IntPtr lua_State);

Every .Net function exposed to Lua must return an int and takes a pointer to the Lua state as its single argument. 

The Lua state object is used to get the parameters for the function along with any other variable values you need for your logic to work. 

Communicating with Lua and the Lua stack 
You do not operate on the Lua state itself, instead you call Lua C library functions which all takes the Lua state as parameter. 

Lua uses a stack for all communication from .Net to Lua (and from any other language to Lua)If you want to create a new object in Lua (called a Lua table) you use the stack available from the Lua state to create it and set values of any desired fields. 

In short, you will need wrapper functions in .Net to operate on the Lua stack, and Lua exports a whole bunch of functions that operates on this stack, which I will show later. 

A complete guide for the lua stack can be found in the Lua documentation, section 3 at http://www.lua.org/manual/5.1/manual.html 

Lua wrappers and the Lua.h source code file
Lua has an API function for registering a function from another language, its quite simple and when wrapped in .Net I created one that looks like this:

public void RegisterLuaFunction(Lua.LuaFunction func, string luaFuncName)
{
   //call the lua_register API function to register a .Net function with
   //the name luaFuncName and a function pointer func
   //the function pointer is defined using the delegate shown earlier
   //when making the correct Lua function signature for .Net functions
   Lua.lua_register(m_lua_State, luaFuncName, func);

   //make sure the delegate callback is not collected by the garbage collector before
   //unmanaged code has called back
   m_refs.Add(func);
}

Dont worry too much about the m_refs.Add(func); call. 
When I first started out creating a Lua wrapper I learned the hard way (debugging debugging debugging) that .Net garbage collects delegates, in use for Lua callbacks, before I intended .Net to do so. 

When Lua calls back into .Net, the function pointer is suddenly no more valid, and a runtime exception occurs.

By maintaining a list of references to registered Lua callbacks in .Net, I make sure that the garbage collector wont collect the functions pointers before I want it to. The list Im using in my wrapper is defined as this:

private static List<Delegate> m_refs = new List<Delegate>();

When I close Lua I just empty the list of refs and they will be collected and I will be happy.
The wrapper for the register function looks like this:

//definition from lua.h source code file
//#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
public static void lua_register(IntPtr lua_State, string n, LuaFunction func)
{
   lua_pushcfunction(lua_State, func);
   lua_setglobal(lua_State, n);
}

You might wonder why theres no DLLImport Attribute.
Take a look at the definition from lua.h, its actually a macro using two other Lua API functions. These two functions must be wrapped as well.
Lua uses macro definitions here and there, actually lua_pushcclosure and lua_setglobal is also just macros:

//#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
public static void lua_pushcfunction(IntPtr lua_State, LuaFunction func)
{
   lua_pushcclosure(lua_State, func, 0);
}

//#define lua_setglobal(L,s)     lua_setfield(L, LUA_GLOBALSINDEX, (s))
public static void lua_setglobal(IntPtr lua_State, string s)
{
   lua_setfield(lua_State, LUA_GLOBALSINDEX, s);
}

The lua_pushcclosure and lua_setfield functions is actual C API function and is lua.h defined and wrapped like this:  

//LUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
[DllImport("lua5.1.dll")]
public static extern void lua_pushcclosure(IntPtr lua_State, [MarshalAs(UnmanagedType.FunctionPtr)] LuaFunction func, int n);

//LUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);
[DllImport("lua5.1.dll")]
public static extern void lua_setfield(IntPtr lua_State, int idx, string s);

This is getting a bit boring I hope I did not lose you completely there, if I did Im sorry 🙂 
The point is to show how Lua API functions can be put in a .Net wrapper that emulates the complete Lua API. 

Registering a .Net callback funtion with Lua 
Lets imagine that we have created a game and in that game we have created a class in .Net which contains methods for manipulating a “NPC player” object. 
Now we want to be able to create combat scripts, task scripts, AI scripts etc. 

Furthermore we want users of the game to be able to create their own levels and define behaviour for NPC characters in that level. 
Most users can learn to write a Lua script and we choose to expose some functionality from the “NPC player” class. 
We fire up an instance of Lua by creating a Lua state, and then we register some .Net functions with Lua. 

Somewhere in our ScriptEngine we have defined: 

 
private static IntPtr m_lua_State = IntPtr.Zero; 

And open Lua: 

 
m_lua_State = Lua.lua_open(); 

//open Lua libraries 
Lua.luaL_openlibs(m_lua_State); 

Our NPCPlayer class definition:

 
public class NPCPlayer
{
  bool InCombat(string characterName)
  {
      //not implemented, always in combat
      return true;
  }
  int Lua_InCombat(IntPtr m_lua_State)
  {
      //get the characterName from Lua
      string cName = string.Empty;
      //if theres a sring argument on top of the stack,
      //LUA_TSTRING = 4 see lua.h
      if (lua_type(m_lua_State, -1) == 4)    
      {
          value = lua_tostring(m_lua_State, -1);
          //pop value from stack
          lua_pop(m_lua_State, 1);
          //the stack is now 'balanced',
          //we got 1 argument, we popped 1 argument
          //now return 1 argument based on the result from InCombat(string)
          //push the return value on the stack and return 1
          Lua.lua_pushboolean(m_lua_State, InCombat(cName));
          return 1;
      }
      else
      {
          //error, invalid argument or no argument on the Lua stack
          //check Lua script for errors and optionally ask Lua for an error message
          //clear the stack
          lua_settop(m_lua_State, 0);
      }
      //sigmal no return value, something went wrong
      return 0;
  }
}

None of our methods match the Lua signature so we have to create Lua ‘trampolines’ for them and handle the Lua communication specifics in them. We register a Lua function callback for the NPCPlayer class like this:

RegisterLuaFunction(new Lua.LuaFunction(Lua_InCombat), "InCombat");

Calling the registered C# method from Lua
The Lua_InCombat method can now be used in a Lua script, Lua will pass the string parameter on its stack structure.

The Lua script could look something like this:
characterName = ‘Winnie the pooh’
winnieFighting = InCombat(characterName)

Its perfectly possible to mess up by calling the Lua function without any parameters or a parameter of a wrong type, there is no type checking, other than the defensive code you can and should implement in your .Net methods.

This concludes the post about registering and using c# methods from Lua.
Hope you found it usefull, please feel free to comment.

Thue Tuxen



Check out part III with source code for a simple lua script engine including a full managed wrapper and a sample program.


Design a site like this with WordPress.com
Get started