This luaObject must be a string or a number; otherwise, the function returns 0 (the null pointer). This function does not create a new string, but returns a pointer to a string inside the Lua environment. Because Lua has garbage collection, there is no guarantee that such pointer will be valid after the block ends. Luagetcfunction converts a luaObject to a C function. String1 = 'Lua'; print(string.upper(string1)) print(string.lower(string1)) When we run the above program, we will get the following output. LUA lua Replacing a Substring. A sample code for replacing occurrences of one string with another is given below. When you run the program, you will get an output of the first line of test.lua file. For our program, we got the following output.- Sample test.lua This was the first line of the statement in test.lua file for us. Also the line '- End of the test.lua file' would be appended to the last line of the test.lua code.
The lua source can be found at the lua website here. We'll be using the latest version, 5.2.3 (though other recent versions of Lua will behave similarly).
Once you have the latest lua source, it's time to build it. (Yes, you could just download header files and the .dll, but what's the fun in that? When available, it's always better to have the source, that way you can see how things are really working -- and you can debug more easily). Using visual studio:
- Open up Visual Studio, and create a new project
- Create a win 32 console application
- In the Project Creation wizard, check the 'static library' radio button to build as a static library.
- Add the lua source to the project. Just dragging the files directly from their folders into the project works well for this.
- There are two source files that you don't need: lua.c and luac.c. These files contain the main program for the command line interpreter and the bytecode compiler, respectively. You can remove this files from the project if you wish. If you are building as a static library, having more than one main won't be a problem. However, if you are building as an executable, then you will need to exclude one of these files from the project. Right-click on them in the project explorer and select 'Exclude from Project'
You now have a project that you can add to any solution that needs lua. Once you have added the lua project to your game, you need to do a few more steps:
- In the properties for the project that is using lua, be sure that the directory that contains the lua .h files is included in the set of include paths. If at all possible, make these paths relative, and not absolute
- Your project will need to get at the .lib files for the lua. There are a few ways to do this:
- Add a reference from your project to the lua project. Right-click on your project in the project explorer, and select References:
Add a new reference:
Select the lua project: - Or, add Lua.lib to 'Additional Dependencies' (in the Librarian/Genrerl tab of the Project Property Pages) and add the directory where Lua.lib lives to 'Additional Library Directories' (also in the Librarian/Genrerl tab of the Project Property Pages).
- Add a reference from your project to the lua project. Right-click on your project in the project explorer, and select References:
Once we have build Lua, and set up our project dependencies correctly, we are ready to use in on our application,
First off, we need to include the proper header files. Since Lua is ANSI C, if we are coding in C++, we will need to enclose the #includes in extern 'C':
![C Test If Lua String Parameter C Test If Lua String Parameter](https://www.programmersought.com/images/737/ea459f915e6a1ff839b50d08f2ec1189.png)
Everything that we need to mantain the current state of the interprer (all global tables, etc) is stored in a variable of type lua_State. The first thing we need to do is create an initial state (essentially, an instantiation of the lua interpreter), which is done by the call:
Every time we want to access the interpreter, we need to pass in this state variable. We can actually have as many instances of Lua state variables as we like (for instance, if we wanted to run separate instances of the interpreter on separate processors, or we wanted different scripts to have different global namespaces), though typically people just use one instance of the interpreter that all scripts use. The global tables in this state variable contain all 'core' functions, but none of the libraries. The libraries contain a bunch of important functions -- including everything in math, and i/o functions like print -- so we'd like to load them. We can load libraries with the call:
So, now we have the skeleton of a main function:
We are ready to start using lua!
We will start with the simplest way to use lua -- have the interpreter execute a file. This is functionally equivalent to the dofile command from within lua (and unsurprisingly, has the same name!). To execute the file 'test.lua', we can use the call:
Note that if we are using relative paths other than absolute paths under windows, then the system will look in the current working directory -- which is the directory that the executable file is in (if you double-click on the executable), or the directory that the project is in (if you run from within Visual Studio) You can, of course, change the working directory that the debugger uses under the project settings in Visual Studio.
So, if we use the following myFile.lua:
when the command luaL_dofile(L, 'myFile.lua') is executed, the following will be printed out
Note that the dofile command not only computes these values and prints them out, it also adds the fib function to the global namespace of our lua enviornment (stored in the C variable L).
We can also call lua functions directly from C/C++, and get back the return values to use in our C/C++ code. To call a lua function we:
- Push the function on the top of the lua stack, using a call to
- lua_getGlobal(lua_state *L, char *globalName)
- Push the arguments to the function on the lua stack, using the functions:
- lua_pushnumber(lua_state *L, float number)
- lua_pushstring(lua_state *L, char *str)
- lua_pushboolean(lua_state *L, bool)
- lua_pushuserdata(lua_state *L, void *userdata)
- lua_pushnil(lua_state *L)
- Call the function, using the function:
- lua_call(lua_state *L, int numArguments, int numReturnValues)
We need to pass in both the number of arguments that we are passing in, and the number of arguments that we expect in return. Lua is very loose about the number of arguments and return value, but C/C++ is less so -- hence we need to be explicit when calling lua from C/C++. - Extract the return values, using the functions:
- int lua_tointeger(lua_state *L, int stackLocation)
Grab an integer value off the lua stack. The first return value is at index -1, the second return value is at index -2, and so on. - double lua_tonumber(lua_state *L, int stackLocation)
Grab a double value off the lua stack. The first return value is at index -1, the second return value is at index -2, and so on. - const char *lua_tolstring(lua_state *L, int stackLocation)
Grab a string value of the lua stack - int lua_toboolean(lua_state *L, int stackLocation)
Grab a boolean value off the lua stack
Note that these functions 'peek' at the lua stack, they don't actually remove any values from the stack. (That is done by the next function) - Pop the return value(s) off the top of the sack (this is just to clean up) with a call to
- lua_pop(lua_state *L, int numReturnValsToPop);
Let's look at a second example. Assume that we had defined the following lua function add (that we could define by calling lua_dofile):
We could call this function to add from C/C++ with the code:
So now you could write scripts that you can call from your game engine. However, these scripts won't be very useful if they can't interact with your game objects -- you need a way for your scripts to affect the game world. To do that, you need to be able to call C/C++ functions from lua. Since Lua and C++ have very different conventions for how functions are called, there is a little bit of wrapper work that needs to be done. First, write a C function that takes as input a Lua state variable (the parameters for the function will need to be extracted by hand from the lua stack -- this is slightly tedious, but not too difficult.) Then, the function will need to be registered with lua.Step 1: Writing a C function that Lua can call
C/C++ functions that are called from lua need to take as an input parameter the lua state. The parameters can be examined on the call stack using the functions lua_tointeger, lua_tonumber, etc (described above). The first parameter is at index 1, the second parameter is at index 2, and so on. Once we have extracted the parameters, we do our calculation, and then push the result on the top of the stack.
Let's look at a slightly more complicated C function. We can write C functions that takes a variable number of parameters, and returns more than one return value. While the previous function assumed that we were passed in two parameters, we can instead query the lua state to see how many parameters were actually passed into the function. The number of parameters is stored on the top of the stack, which can be accessed by a call to lua_gettop(lua_state *L). Let's look at a function that takes in multiple parameters, and calculates the sum and average of all parameters that were passed in:Step 2: Registering the C function for lua
Once we have written the function, we just need to register it with lua. Download permainan clash of clans mod apk 2018. That is, we need to add the name of the function to the global lua namespace, and provide a pointer to the function so that lua cal access it. There is a helpful macro for this: lua_register(lua_state *L, const char *name, functionPointer fn). So, to register the above two functions:
Step 3: Calling the C funcion from lua
This part is easy -- once the function is registered, lua can call it like any other function.
So, the complete round trip is:
- Start the lua interpreter
- Register the C functions you want lua to use
- Call a lua function from within C, either by a call to luaL_dofile, or by calling a lua function directly
- The lua function that you called from C can access the C function
We can also send a string straight to the lua interpreter, and it will be executed just as if that string was in a file that was executed with a dofile. So, we could do something like:
and we would get the output:
We could thus create a braindead interpreter as follows:
Note that this would not work at all in a game environment! We will look at how to embed a command-line lua interpreter within a game next time. For now, this is enough for us to play around with a bit.
Now we are ready to get our fingers dirty!
- Download the following project, which contains a basic skeleton lua framework
- Write a function in C (exposed to Lua, much like average and cAdd) that takes as input an integer n, and returns all prime numbers less than or equal to n.
- Test your primes function in the interpreter with 'print(primes(100))'
- Write a function in lua nthPrime, that takes as input a number n, and returns the nth prime number. So, nthPrime(6) should return 13. We'll define nthPrime(1) to be 2, and nthPrime(0) will be undefined. Your lua function should call the c primes function
- Small change in how lua does variable numbers of arguments: From the notes Alas, this does not work. But we can fix it with a simple change:
- Small change in how lua does variable numbers of arguments: From the notes
- Write C code that computes the 100th prime number by calling the lua nthPrime function, and prints the value out using printf. So, C calling Lua that calls C.
|
The problem
Lua lacks a C-style
switch
[1] statement. This issue has come up a number of times on the mailing list. There are ways to emulate the same effect as discussed here. The first question to ask is why we might want a switch statement rather than a comparison chain as such:
When there are many tests as such, the comparison chain is not always the most efficient. If the number of elements in
letters
is M and the number of tests is N, then the complexity is O(M*N), or potentially quadratic. A more minor concern is the syntax redundancy of having 'v
' for each test. These concerns (minor as they may be) have been noted elsewhere as well ([Python PEP 3103]). If we rewrite this as a lookup table, the code can run in linear-time, O(M), and without the redundancy so that the logic is easier to modify at whim:
C compilers can optimize the switch statement in a roughly similar way via what is called a jump table, at least under suitable conditions.[2]
Note how the table construction was placed outside the block to avoid recreating the table for each use (table constructions cause heap allocations). This improves performance but has the side-effect of moving the lookup table further from its usage. We might address that with this minor change:
The above is a practical solution that is the basis for the more elaborate approaches given below. Some are the below solutions are more for syntactic sugar or proof-of-concept rather than recommended practices.
Simple Table of functions
A simple version of a
Usage (Note, that in the following example you can also pass parameters to the function called) :- This is pseudocode for the above: switch
statement can be implemented using a table to map the case value to an action. This is very efficient in Lua since tables are hashed by key value which avoids repetitive if <case> then .. elseif .. end
statements. Table elements called with loadstring()
Here's a neat and compact version using the
loadstring()
function and calling each element in a table of cases. This method is close to Python's eval()
method and it's nice looking. It allows for arguments to be put in formatted. Case method
This version uses the function
switch(table)
to add a method case(table,caseVariable)
to a table passed to it. ![C Test If Lua String Parameter C Test If Lua String Parameter](https://defold.com/manuals/images/extensions/cppfile.png)
Caseof method table
Here's yet another implementation of a 'switch' statement. This one is based on Luiz Henrique de Figueiredo's switch statement presented in a list message dated Dec 8 1998, but the object/method relationship has been flipped around to achieve a more traditional syntax in actual use. Nil case variables are also handled - there's an optional clause specifically for them (something I wanted), or they can fallback to the default clause. (easily changed) Return values from the case statement functions are also supported.
Here's sample usage: Switch returns function instead of table
Yet another implementation of an even more 'C-like' switch statement. Based on Dave code above. Return values from the case statement functions are also supported.
Example usage: Note that this works, but trashes the gc with a function closure each time the switch is used (as do most of the examples on this page). Still, i like the way it works. Just don't use it in real life ;-) --PeterPradeSwitch returns callable table instead of function
This one has the exact same syntax as the one above, but is written much more succinctly, as well as differentiates between the default case and a string containing the word 'default'.
Nil
here is an empty function because it will generate a unique value, and satisfy the [nilpotence] requirement in the return
statement call, while still being having a value of true
to allow its use in the and or
ternary. In Lua 5.2, however, a function might not create a new value if one is present, which will raise problems if you somehow end up using switch
to compare functions. Should it ever come to this, a solution would be to define Nil
with yet another table: setmetatable({}, { __call = function () end })
. A case-insensitive variant can be made by adding
if type(item) 'string' then item = string.lower(item) end
, provided all the keys of the table are done the same way. Ranges could potentially be represented by an __index function metatable on the cases table, but that would break the illusion: switch (case) (setmetatable({}, { __index = rangefunc }))
. Example usage:
I can't say anything for its resource usage, however, especially compared to other examples here. Using vararg function to build case list
In the interest of more 'stupid Lua tricks', here's yet another implementation: (Edit: It is necessary that the default functionality is put last in the .. parameter)
Example usage: Case expression types other than just matching a value
Here's one from TheGreyKnight?, which can handle cases representing ranges, lists and default actions. It also supports mismatch cases and fall-through (ie, continue with the next statement). The part that checks for the '-fall' suffix could probably be made more efficient, but I think this version is easier to read. The functions which are used as the bodies of the cases are passed a single parameter, which is the final form of the switch expression (a feature I've longed for in switches for ages) The supporting functions contain(x, valueList) and range(x, numberPair) merely test whether or not x is a value in the table valueList or a number in the closed range specified by the two elements of numberPair. Example Usage:C Test If Lua String Parameters
Another form
It avoids repeating functions, since if tbl's entry is a string/number, it follows this value as the case to seek for. I would call this multiple case statements. Example usage:A Case Statement implemented with Token Filter Macros
My feeling is thatswitch
is the wrong model, but that we should look at Pascal's case
statement as more appropriate inspiration. Here are some possible forms: You can provide a number of values after
is
, and even provide a range of values. matches
is string-specific, and can take an extra parameter which is filled with the resulting captures. This
case
statement is a little bit of syntactical sugar over a chain of elseif
statements, so its efficiency is the same. This is implementable using token filter macros (see LuaMacros; the source contains an example implementation), so people can get a feeling for its use in practice. Unfortunately, there is a gotcha; Lua complains of a malformed number if there is no whitespace around
.
. Also result
has to be global. Metalua's pattern matching
MetaLua comes with an extension that performs structural pattern matching, of which switch/case is just a special case. The example above would read:
No special handling currently exists for regular expressions string matching, although it can be worked around by guards. Proper support can be added quite easily, and will likely be included in a future release.
Relevant resources:
* Step-by-step tutorial about implementing a pattern matching extension[3], and the corresponding sources[4].
* The latest optimized implementation[5]
C Test If Lua String Parameter
Object Oriented Approach
You can find full code in SwitchObject.Comments
I don't get it. I'm a hard core C/C++ programmer but not once have I longed for
switch
in Lua. Why not take this to its extreme and just have Lua parse a real C switch statement? Anyone who can achieve that will learn why it wasn't necessary in the first place. --TroublemakerHow about to avoid: a) a linear search through options, b) to avoid creating garbage every time the case is used, and c) because the if-elseif-else solution is ugly. The condition is repeated N times which obscures and complicates the code. A simple switch on numbers could jump quickly to the code to be executed and doesn't have to generate a closure or a table every time as in the code below.
Actually, I've never used this code as a
switch
statement. I thought it made good example code for Lua's features and I may use it one day, but I never have! :-) I think its because you have the associative arrays/tables to map values, so you can design around having to need a switch statement. The times when I do think about needing a switch is when I'm switching on value type. --AlsopuzzledI've never really needed a
switch
in Lua either, but these examples made me bend my brain trying to see why they work. Lua's flexibility continues to amaze me. I'm now that much closer to the ZenOfLua. --InitiateThe issues with these implementations are that they either can't access local variables or they create not just one closure but one closure per switch-branch plus a table. As such, they aren't particular good as substitutes for a
switch
statement. That being said, I haven't been suffering too much pain related to the lack of a switch statement in Lua. --MarkHamburgThe lookup table example is a perfectly practical and readable solution that doesn't suffer from those problems at all. It's even mentioned in the page that examples beyond that point are mostly non-practical thought experiments -- Colin Hunt
I am using LUA for scripting my self created web server module. It's terribly fast (and much much faster than my previous PHP version). In here, a switch statement would really be great to case through all GET['subfunction'] possibilities. The only reason is that the only thinkable alternative (if-elseif) is ugly. The other alternatives are as previously indicated very beautiful, world-opening, but a terrible waste of resources. --Scippie
Edit: Maybe I was wrong about the 'terrible waste of resources'. This is what scripting is all about and the language is made to be handled this way. --Scippie
You don't need a switch statement, if you can just map with a table or use elseifs. The real problem starts when you want to use fallthrough. I am currently working with a database and I need to be able to update it. Since it needs to be updated one step at a time, you jump to the place that updates to the next version and then fall-through until you arrive at the newest version. For that, though, you need either computed goto or a switch statement. Which Lua both lacks. --Xandaros
'@Xandrous There is a goto now'
The above code was pulled from lua-l or donated by Lua users. Thanks to LHF, DaveBollinger?, EricTetz, PeterPrade. RecentChanges · preferencesedit · history
Last edited December 20, 2016 9:50 am GMT (diff)