Hi, everyone. So, this is Frank van Bever with Lua for the lazy C developer.
Hi, I'm Frank van Bever, and I'm here to talk to you today about the Lua programming language
and specifically for lazy C developers. So, first of all, who am I? Frank, I work for a
company called Mind, free and open source. Well, there's consultancy, specialized in free and
open source software for embedded systems. If you're the kind of person who enjoys the
referencing pointers and you're looking for a job, check out our website or come to talk to me
in the hallway after the presentation. So, with that out of the way, why am I here? I am here
to talk to you about being a virtuous software developer. So, the man on the photo is Larry Wall.
He's mostly known for being the creator of the Pearl programming language, but he also coined
these three virtues of a great software developer. These virtues are laziness, impatience and hubris.
I want to focus on the laziness virtue specifically today. And so, he defines laziness as the quality
that makes you go to great efforts to reduce overall energy expenditure. It makes you write
labor-saving programs that other people will find useful and document what you wrote so
that you don't have to answer so many questions about it. Now, in my day job, I'm mostly a C
developer and, well, if you have any experience with that, you know that there can be quite
some energy expenditure involved in doing that. So, introducing the Lua programming language,
quick introduction. It's a programming language. It's multi-paradigm. You can program in both an
object-oriented style. It uses prototype inheritance. So, for people used to Java or C++ might seem
a bit strange. It has the same inheritance model as JavaScript. It actually has quite a bit of
resemblance to JavaScript in some ways. They were both created around the same time. Big
change from C is that Lua is dynamically typed compared to C's static week typing. So, you can
just declare a variable. You don't have to specify the type. You don't need to care about it. Lua is
small. That can be interpreted in many ways. Lua installation that I have on my machine is about
250 kilobytes. So, it's really perfect for embedded systems where often you're constrained. But it's
also small in the sense that it has, like, language itself. It's like a small set of meta
features that you can use to then build whatever it is that you need. And one example of that,
for example, is that there's only one data structure, a table, which is like a map or a
Python dictionary. And by basically constraining the behavior of this table, you can get all
kinds, well, you can basically build all kinds of other data structures. So, yeah, basically it
being a small language, C developers should feel right at home. Another big difference is Lua is
garbage collected compared to having to do manual management in C. Lua will basically take care of
that for you. And most importantly, for a C developer, Lua is actually also a C library. What
does that mean? Well, on the left, you have Hello World in Lua syntax. And this program can just
as well be expressed using Lua C API, which you can see, well, yeah, my left, left, right. So,
for you, also on the left side, the Lua C API, these two are equivalent. So, how does this,
well, so how does this work? Well, Lua has as a stated design goal that it should be both an
extension language, meaning that you can call Lua from C, so extend your C application by using
Lua, as well as an extensible language, meaning that you can call into your C code from your Lua
application. And the way it does this is by using a stack. So, this stack nearly, so the C API,
everything it does is manipulate this specific stack. And this fixes two important impedance
mismatches. So, like I mentioned before, first thing that it fixes for you is the static typing
versus the dynamic typing. If we had to map the internal state of these Lua, of all the internal
Lua types to C types, well, a knee jerk reaction would be union types structs. But that's a row
that quickly leads to insanity. By using this stack as like a clear boundary line between the two,
it's easy to translate your Lua variables into, well, Lua variables into C variables and vice
versa. Second thing that it fixes for you, the second impedance mismatch is this manual memory
management that you need to do in C while Lua is garbage collected. By popping, well, by pushing
and popping from the stack, it is clear when the handover happens of memory from one, from one
side to the, well, from the C side to Lua and vice versa. So, where might it make sense to use Lua?
So, well, as you can imagine, using dynamically typed scripting language that is garbage collection
comes with a performance hit. So, you need to keep that in mind. But so, for some cases where it
might be useful is taking care of tedious stuff that runs sporadically. So, especially, yeah,
there's no better way to get me to run to the coffee machine in a grumpy mood than having to
do a lot of string manipulations in C, like an edible. And so, stuff like that, especially config
files, for example, it makes, it can make sense to say, okay, you know what, we're going to call out
to Lua, we get our config, we put it in a C struct, and then from there, we can go on with our
application. Prototyping is another place where I found that Lua really shines. So, sometimes you
need to, you have some software that you need to build, and you only get some vague requirements
communicated to you. It actually helps to have the agility of this dynamic typed garbage
collected language, but still have the flexibility of calling maybe into C dependencies that you
will need later on. And then just, as you go, switch out C from Lua and Lua from C. And the
third thing, and really, this is, in my opinion, is where Lua shines the most is, so, plugins and
extensibility. If you want to make your application extensible, your C application extensible, so,
if you just do it with C, you would say, okay, you need to build a shared object using this
specific API, and then we'll do a DL open. Pretty annoying. Sometimes, if you have to explain to
some people what a compiler is, then it already goes beep in their head. So, Lua, you just define a
simple API and makes your application almost immediately extensible so that a third party can
inject their logic into your application. It means that you don't have to implement all the
features that people need. They can do it for themselves very easily. So, how hard is it to do
this? Well, so, a bit of a risky move to have only code on the slide, but let's do this. Imagine
you have a Lua file that contains a trivial function that returns the sum of two integers,
A and B. You want to call this from your C code, you initialize your Lua state, you load this
file, file gets executed, well, you need this file gets put on the stack, you need to execute this
through, well, a Lua call. This will register everything that is in the file into the global
scope, and at this point, this add function becomes available to your Lua. You can get it,
you retrieve it from the global scope, it gets put back on the stack, you push both arguments
onto the stack, you do another call, this time specifying that there are two arguments, one
return value, and the final argument is basically that, well, it's for error handling that's beyond
the scope of this presentation. Your Lua function will be executed, and then it puts the return
value onto the stack, and then using this Lua to integer call, you can retrieve it from the stack,
you're back in C land, your Lua has finished running, and so eight function calls, and you
unlock a whole new world of possibilities in your C application. Of course, this is, well,
check your return values, that's omitted for the slide, of course, make sure that, yeah, check for
errors, that's important. So the other way around, you can have a, so we just covered the calling
Lua from C, another, the other option is, of course, that you call your C code from Lua,
the way to do that is by creating these Lua C functions, they always have the same signature,
they take single argument, this Lua context, Lua state, and they return an integer, which is the
number of variables that they put on the stack as return values. Functions will always look the
same, pop the arguments from the stack, do some useful work, push the results back onto, push
the results back onto the stack, you create an array of this Lua registry functions where you
have a name plus a pointer to the function, a sentinel value to mark the end of the array,
and then you have a Lua open underscore and then the name of your, the name of your, the name of
your module, which returns a new lip, so this will put your module that you just created onto the
stack and return one for a single return value, and by doing this you can then load the module in
your Lua code and then call into the C code without any, well, call into the C code and get the
result back. Of course, having to do, well, having to build a shared object might be a bit annoying,
you have to convince your, you have to convince your build system to create a shared object for
you, there's no, and there's no way to share then between a C application and your Lua code,
so there's a, there's a fix for that actually, you can publish internal functions in your Lua
application, so functions that exist within your C application and make them available to a Lua
context that is created in that application, by combining basically the previous two approaches,
so same thing here, subtract function defined as a Lua C function, returns the result of A-B,
you register it and then in your code you can just say, you can just push this Lua new lip,
so the module that will be created, it's actually, it's actually a table with function pointers
because everything is a table in Lua, and then instead of, well, instead of it being a shared
object and being registered, you can just say, okay, the thing that I just put on top of the
stack, make it global and have it be, and make it global under the following name, so in this case,
C arithmetic, and in that case, any other Lua script that you use doesn't even have to load the
module, it will automatically be loaded, it's already in the context, and so wherever you're
doing this, you can just say, you can just call this C arithmetic module and then the functions
that exist within there, so in short, Lua can, well, you could say Lua can help you get more done
quicker, but keeping this, being a virtuous programmer in mind, I think that Lua can definitely
help you embody this virtue of laziness, and so there's some time left even. I, all the code
that was in the presentation, I basically have some executable examples for that open GitLab,
if you want to check it out, and that's it, so thank you for your attention. If you have any
questions, or you want to tell me I'm wrong, or you want to talk to me about something I'll be
in the hallway after your presentation, so thank you. Thank you. We have 20 seconds, if we have
one question maybe, very quick one.