|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis article presents a thin wrapper around Lua, see [1], and Luabind, see [2], for .NET: with it you can embed a scripting engine with a C, C++ backbone into your .NET applications. If you are not familiar with Lua and Luabind, a small introductory example is also given below. Lua, an embeddable C scripting languageHere are some quotes extracted from the Lua "about" page: "Lua is a powerful light-weight programming language designed for extending C, C++ applications." "Lua is a language engine that you can embed into your application. This means that, besides syntax and semantics, Lua has an API that allows the application to exchange data with Lua programs and also to extend Lua with C functions. In this sense, Lua can be regarded as a language framework for building domain-specific languages." Usually, using Lua in an application is done with the following steps:
Create a Lua state"The Lua library is fully reentrant: it has no global variables. The whole state of the Lua interpreter (global variables, stack, etc.) is stored in a dynamically allocated structure of type As mentioned above, lua_State* L = lua_open(); Bind methods to LuaSuppose that the following method need to bound: void my_print( const char* str ) { printf( str ); } First, we need to make a function wrapper for int my_print_lua(lua_State *L) { /* get the number of arguments (n) and check that the stack contains at least 1*/ int n = lua_gettop(L); if (n<1) { lua_pushstring(L, "not enough arguments"); lua_error(L); } /* try to cast argument to string and call my_print, - remember that Lua is dynamically typed - we take the first element in the stack */ my_print( lua_checkedstring( L, 1) ); /* my_print does not return values */ return 0; }; At last, the method is registered in Lua using: lua_register(L, "pr", my_print_lua); Remark: Handling the Lua stack can become tedious and error-prone. Hopefully, Luabind is here to simplify (a lot) the wrapping task. Executing Lua scriptsConsider the following script: s = 'this is a test'; pr( s ); As one can see, Lua syntax is quite straightforward. In the script, we see that the method we bound ( const char* str = "s = 'this is a test';pr( s );";
lua_dostring(L, str);
The program will output: this is a test
Clean and deallocate stateWhen you are finished, do not forget to call lua_close(L);
Luabind, simplifying thingsAs mentioned before, handling the Lua state is a tedious work that we would like to avoid. Luabind uses template meta-programming to simplify things for us. Using Luabind, the previous steps become:
Remarks:
LuaNET, the wrapperSo what about executing Lua script in .NET applications? This should not be a major problem, just the matter of writing a managed C++ wrapper. Remarks:
State, wrapping lua_StateThe managed class Here's a small example that creates a state, sets some variables and executes a script:
Note that LuaObject, wrapping luabind::object
Since Lua is dynamically typed, you need to check the type of the L.DoString("s='string';");
L.DoString("print('s: ' .. tostring(s));");
LuaObject s=state.get_Global("s");
s.ToString(); // ok
s.ToDouble(); // fails, s is a string
If the object is a L.DoString("t={1,'string'};");
LuaObject t=L.get_Global("t");
System.Collections.IDictionaryEnumerator te = t.GetEnumerator();
while( te.MoveNext() )
{
System.Console.WriteLine("t...(" + te.Key + "," + te.Value +")");
};
Loading librariesLua comes with a set of default APIs to handle strings, table, IO, files etc...To load these APIs, use Lua.Libraries.DefaultLibrary.Load( L );
Luabind is loaded using Lua.Libraries.LuabindLibrary.Load( L );
You can wrap up your API and load them in .NET using the same method as Using the demoThe demo features Lua 5.0 and Luabind. You need to recompile all the projects and launch LuaNetTest. History
References
|
||||||||||||||||||||||