How To Use C Functions In Lua
Calling C/C functions from LUA. In order to embed a C function in LUA you have to register it to the LUA state, this is done by using the luaregister macro. This macro takes 3 parameters: #define luaregister(L,n,f) The 1st parameter is the LUA state pointer, the 2nd one is the LUA function name and the 3th one is the C function name. The first step is to define the function. All C or C functions that will be called from Lua will be called using a pointer of this type: typedef int (.luaCFunction) (luaState.L); In other words, functions must have a Lua interpreter as the only argument and return only an integer.
The C/Invoke Lua Binding uses the new Lua module system, so to use C/Invokein your Lua programs, load the module like so:
To call C functions easily without writing a Lua module, declare a newinstance of the clibrary class to load a dynamic library. The clibraryinstance has methods which allow you to load functions and variables, similarto dlopen() and dlsym() on UNIX, except that you also specify the types ofthe parameters and the return value:
Here we load libc.so.6 (you will have to adjust this for operating systemsother than GNU/Linux) and then call get_function on the returned instance.We pass arguments to get_function to specify a function named 'getpass' whichreturns a type Cstring (essentially a const char *) and takes a single argumentof type Cstring. get_function returns a callable Lua function object, which weassign to a variable also named getpass. This function is now usable:
Thus we have now integrated the previously unavailable getpass() functioninto Lua, without writing any C!
The clibrary class also has a method to create a callback, which isanalogous to a C function pointer, and which allows C libraries to callLua functions. There is also a cstructure class for defining struct types,as well as a cinv class which provides global helper methods toassist with data marshalling.
There are two sorts of types in cinvoke_lua, built-in and user-defined. Thelist of built-in types is in the class reference below, and includes most ofthe basic types from C (integers, floating point values, etc.). These aremarshaled to and from Lua as one would generally expect. Values of type Ccharare marshaled as Lua strings with length 1, not as their byte (integer) value.
Another built-in type is Cstring, which as mentioned earlier is usefulfor marshaling constant strings. Note we must emphasize the 'constant'; Lua strings are immutable and passing them to a function which writes to theirmemory is extremely bad. You can also have functions which return stringvalues, in which case the value returned is truncated at the first 0 character.
This limitation on returning string data as well as almost any otherlimitation can be overcome with the use of arrays and pointers. To declarean array type, use the cinv.array function on a non-array type. Arrays inLua are represented in the normal manner with a table:
As you can see, with an array you can have values written back to Lua viaparameters. This function also uses the Cptr built-in type as the returntype. A ptr is an opaque object (actually represented by a string) whichcan be used to send or receive raw pointer values to C. They can then beused with functions such as cinv.ptr_to_array and cinv.ptr_to_struct tomarshal values which would otherwise be impossible for C/Invoke to determine(for example, returning an array directly from a function is not allowedbecause C/Invoke doesn't know the length of the returned value). Using ptrsalso allows you to capture data returned by functions like malloc() and thenlater return their pointer values back to the C library.
In general, you can use arrays whenever you wish to pass a pointer value asa parameter (in C, an array with one element and a pointer are essentially thesame). Ptrs are useful for return values as well as situations where youmust hand-marshal parameters. If you wish to pass a NULL value to afunction, C/Invoke allows you to pass a nil value for an array or ptr. Ptrparams will also accept the integer 0 as a NULL value.
The cstructure class contains one method to create a new structure type.For example, to create the equivalent of the following C definition:
One would do the following:
And to use them:
Struct types cannot be passed by value, only in arrays and marshaled byhand with pointers.
The final built-in type is Ccallback, which represents all C functionpointers. To create an instance of a callback, use the clibrary:new_callbackmethod, passing the Lua function you would like to call instead of the nameof the function to load as in get_function (this method is a member of clibrarybecause it uses the calling convention that the library was declared with):
C:
Lua:
A warning: you should only use callbacks in situations where all calls to the callback are done inside the called function. This will ensure that the Luacontext being called back to is still active. It is especially dangerous fora C function to keep a reference to a callback and then call it later inanother thread; the Lua object holding the callback may have beengarbage collected and the Lua interpreter is not thread safe.
Built-in Types
Cvoid
A placeholder to declare a function with no return value.
Cchar
The char type is always 1 byte wide. This type is marshaled as a Lua stringwith length 1.
Cshort
The short type is marshaled as an integer.
Cint
The int type is marshaled as an integer.
Clong
The long type is marshaled as an integer.
Clonglong
The long long integer type is available on some platforms; it istypically used to represent an 8-byte integer on 32-bit machines.
Cint16
This integer type is aliased to the type which is two bytes wide on the current platform.
Cint32
This integer type is aliased to the type which is four bytes wide on the current platform.
Cint64
This integer type is aliased to the type which is eight bytes wide on the current platform.
Cfloat
C floating point values are marshaled as a Lua number.
Cdouble
C double-precision floating point values are marshaled as a Lua member.
Calling Lua From A C Program - Troubleshooters.Com
Cstring
The string type allows Lua strings to be passed to functions accepting aconst char *. Do not use this type for mutable arrays or to return a valuefrom a function which is not 0 terminated.
Cptr
This type represents a Pointer value, however large that may be on the currentplatform. Values of this type should only be either returned from a Cfunction, or the value nil or the integer 0. You can pass values of this typeto many members of the cinv class to marshal values which would otherwisebe difficult to for C/Invoke to process.
Ccallback
Represents any C function pointer, regardless of the prototype. Valid valuesare generated (with prototype information) by the clibrary:new_callback method.
Classes
cinv
array(type)
Returns a new type representing a C array (passed by reference) of thespecified type. The passed type is not modified.
chararray_to_string(arr[, len])
Converts a Lua array (a table with integer keys) of values of type Cchar to a Lua string. If len isnot specified, the length is determined by the length of the array.
string_to_chararray(str[, includenil])
Converts a Lua string to a Lua array (a table with integer keys) of values of type Cchar. If includenil is true, then the last element of the array will bea 0 byte value.
ptr_to_string(ptr[, len])
Converts a ptr value (presumably pointing to an array of chars) to a Luastring. If len is not specified, conversion continues up until the first 0character.
ptr_to_array(ptr, type, len)
Converts a ptr value to a Lua array of values of the specified type. Thismethod provides a way to unmarshal return values consisting of pointers tostructures.
ptr_to_struct(ptr, type)
Converts a ptr value to a Lua table, with the keys and values set to thefields of the specified structure type. Essentially equivalent tocinv.ptr_to_array(ptr, type, 1)[1].
ptr_to_callback(ptr)
Converts a ptr value to a value suitable for passing as a Ccallback.Useful for C functions which return function pointers.
callback_to_ptr(cb)
Converts a C/Invoke callback returned by clibrary:new_callback to a raw ptrvalue. The returned ptr points to managed memory inside the Lua interpreter,and the same cautions apply when using it as when passing callback values to a function.
sizeof(type)
Returns the number of bytes needed to hold the given type.
clibrary
new(libname[, callingconv])
Opens a C shared library. Libname is a platform-specific string containingthe name of the library to load, i.e. 'libc.so' or 'kernel32.dll'. callingconvspecifies a calling convention to use. Currently supported are 'cdecl','stdcall', 'fastcall', and 'default'. If callingconv is not specified then thedefault is used. Platforms other than Microsoft Windows typically only usethe default calling convention. On Windows, stdcall should be used for allWin32 API functions.
dispose(self)
How To Use C Functions In Lua
Unloads the given library instance from memory.
get_function(self, rettype, name, ...)
Creates a new C function object in the given library, and returns a callable Lua function value.If the function returns void, specify Cvoid for rettype, otherwise specify thecorrect return type. The name parameter is the name ofthe symbol in the shared libary to load. If the function takes parameters, passthe types of the parameters in order after the name. Functions with variableargument lists are not supported. For other limitations, see the documentationon specific types.
new_callback(self, rettype, cbfunc, ...)
Creates a callback object which can be passed as a function pointer to a Cfunction. The arguments are the same as for get_function, except that insteadof a symbol name, a Lua function is passed. This function will then get calledwhen the C code calls through the function pointer. Because C/Invoke cannotcontrol the values being passed into and returned from the callbacks, thereare additional constraints on the types of arguments a callback can take; inparticular, arrays are not allowed as arguments.
It is highly reccomended to only use callbacks in circumstances where thepassed function pointer is called within the context of the C function, andnowhere else. Storing a pointer to a Lua callback and calling it later in the program execution could lead to undefined behavior.
tie_init(self, type, name)
Creates an entry in the library instance for a tied variable, i.e. a symbolin a shared library which points to a global C variable. Only basic types (notstrings, structs, callbacks, etc.) can be tied.
tie_get(self, name)
Returns the value of a tied C variable as a Lua object.
tie_set(self, name, value)
Sets the value of a tied C variable.
cstructure
new(type, name[, type, name ...])
Creates a new structure type. Each pair of arguments to this functionadds a member to the structure. Once a function with the returned type isdeclared, a table value with the given name values as keys can be used torepresent an instance of this structure. Structures cannot be passed to Cfunctions by value; they must be passed in an array. Structures cannot containarrays or callbacks, but they can contain embedded in-line structure types.For example, the following C definition:
Can be represented in Lua as shown:
Embedding LUA in Visual C++ (Custom Functions)Introduction
If you want to know more about how to start using LUA and Visual C++, then please follow the link at the left. The code below is made with LUA 5.0.2.
Calling C/C++ functions from LUA
In order to embed a C++ function in LUA you have to register it to the LUA state, this is done by using the lua_register macro. This macro takes 3 parameters :
#define lua_register(L,n,f)
The 1st parameter is the LUA state pointer, the 2nd one is the LUA function name and the 3th one is the C function name.
For this example we'll create an LUA function that will allow a script to show a message box to the user. We'll call this function alert (inspired by a very very similar JavaScript function).
We first create our internal function, this function is so basic that I don't want to add comments to it :
Then we create our glue function, this is the function that takes care of the link between the LUA engine and your C/C++ program :
This function may require some explanation. The first part is to verify that the stack contains enough arguments, LUA doesn't know how many parameters your C/C++ function will take so it will push all the parameters to the stack. If the scripter has used no parameters than the stack will be empty.
Then we get the first argument from the stack and we verify that it isn't NULL as we only want to work with valid strings :-).
After verifying the string we call the internal alert function (defined above), we foresee two different function calls, the first one is called when there is only one parameter and the second one will include the message box title. If the function has been called with more than two parameters then the extra ones will be ignored.
At the same time the result of our alert function will be pushed as a number. The function will exit with the value of 1 and this tells the LUA engine that we have pushed one value the stack that is used as a return value. Remember, LUA communicates with the stack so return value are pushed on the stack and so the return value of the C function is only to tell LUA how many values the function will return to the script.
Now that we have our glue function, we can register it LUA :
And now that we're done, let's create a new example script that will use our alert function :
You can download the project file or executable for this example below. Enjoy.
Calling LUA functions from C/C++
With LUA it is also possible to call LUA functions from C/C++. This technique can for example be used to allow execution of events by user-defined scripts.
Doing it is pretty simple and requires you only to get the function name and to push the values on the stack. Our alert function can be called as follows :
And this is how we can call the double function (see our example script above) :
This technique is also demonstrated in the download below.
Download
You can download the above test project here (compressed ZIP files) :
The source code of LUA Demo 2
The executable version of LUA Demo 2
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