Introduction
So far I’ve covered wrapping a C library in Lua, writing a Lua module, and calling Lua from C. The next step is using this knowledge to wrap a Lua module in C. Basically, the opposite of wrapping a C library in Lua for use in Lua. In this case we want the library written in Lua and used by C.
Essentially, this is an extension of what was covered in “Calling Lua From C”. Most of the concepts were covered there and this is more about code structure, organization and reusability.
The Lua Module We Want to Wrap
Once again I’m going to use to use the counter example.
counter.lua
local M = {}
local M_mt = { __index = M }
function M:new(start)
if self ~= M then
return nil, "First argument must be self"
end
local o = setmetatable({}, M_mt)
o._count = start
return o
end
setmetatable(M, { __call = M.new })
function M:add(amount)
self._count = self._count + amount
end
function M:subtract(amount)
self._count = self._count - amount
end
function M:increment()
self:add(1)
end
function M:decrement()
self:subtract(1)
end
function M:getval()
return self._count
end
function M_mt:__tostring()
return string.format("%d", self._count)
end
return M
The Wrapper
Just like with the C library wrapper this wrapper extends the functionality by adding a name.
counter.h
#ifndef __COUNTER_H__
#define __COUNTER_H__
struct counter;
typedef struct counter counter_t;
counter_t *counter_create(int start, const char *name);
void counter_destroy(counter_t *c);
void counter_add(counter_t *c, int amount);
void counter_subtract(counter_t *c, int amount);
void counter_increment(counter_t *c);
void counter_decrement(counter_t *c);
int counter_getval(counter_t *c);
char *counter_tostring(counter_t *c);
#endif /* __COUNTER_H__ */
counter.c
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "counter.h"
#include "counter_lua.h"
struct counter {
lua_State *L;
char *name;
};
static void cleanup_stack(lua_State *L)
{
if (L == NULL)
return;
if (lua_gettop(L) > 1)
lua_pop(L, lua_gettop(L)-1);
}
counter_t *counter_create(int start, const char *name)
{
counter_t *c;
lua_State *L;
L = luaL_newstate();
if (L == NULL) {
return NULL;
}
luaL_openlibs(L);
/* lcounter = require("lcounter") */
if (luaL_loadbuffer(L, (const char *)counter_lua, counter_lua_len, "counter.lua") || lua_pcall(L, 0, LUA_MULTRET, 0)) {
lua_close(L);
return NULL;
}
/* c = lcounter(0) */
/* Put our argument (start) onto the stack. */
lua_pushinteger(L, start);
/* Call M(start).
* 1 arguments.
* 2 return values. */
if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
lua_close(L);
return NULL;
}
/* Right now we will either have nil and an error string
* or the counter object returned by new. */
if (lua_gettop(L) != 1) {
lua_close(L);
return NULL;
}
if (lua_type(L, -1) != LUA_TTABLE) {
lua_close(L);
return NULL;
}
/* We're sure we have a table that was returned by new at
* as the only item on the stack. */
c = malloc(sizeof(*c));
c->L = L;
c->name = (name==NULL)?NULL:strdup(name);
return c;
}
void counter_destroy(counter_t *c)
{
if (c == NULL)
return;
lua_close(c->L);
free(c->name);
free(c);
}
void counter_add(counter_t *c, int amount)
{
if (c == NULL)
return;
/* Pull out the add function so we can run it. */
lua_getfield(c->L, -1, "add");
/* Copy (don't move) the counter object so it's the
* first argument. Meaning we're doing M:add. */
lua_pushvalue(c->L, -2);
/* Add the argument. */
lua_pushnumber(c->L, amount);
/* Run the function. 2 arguments. No return. */
if (lua_pcall(c->L, 2, 0, 0) != 0)
cleanup_stack(c->L);
}
void counter_subtract(counter_t *c, int amount)
{
if (c == NULL)
return;
lua_getfield(c->L, -1, "subtract");
lua_pushvalue(c->L, -2);
lua_pushnumber(c->L, amount);
if (lua_pcall(c->L, 2, 0, 0) != 0)
cleanup_stack(c->L);
}
void counter_increment(counter_t *c)
{
lua_getfield(c->L, -1, "increment");
lua_pushvalue(c->L, -2);
if (lua_pcall(c->L, 1, 0, 0) != 0)
cleanup_stack(c->L);
}
void counter_decrement(counter_t *c)
{
if (c == NULL)
return;
lua_getfield(c->L, -1, "decrement");
lua_pushvalue(c->L, -2);
if (lua_pcall(c->L, 1, 0, 0) != 0)
cleanup_stack(c->L);
}
int counter_getval(counter_t *c)
{
int n;
int isnum;
lua_getfield(c->L, -1, "getval");
lua_pushvalue(c->L, -2);
if (lua_pcall(c->L, 1, 1, 0) != 0) {
cleanup_stack(c->L);
return 0;
}
n = lua_tointegerx(c->L, -1, &isnum);
cleanup_stack(c->L);
if (!isnum)
return 0;
return n;
}
char *counter_tostring(counter_t *c)
{
const char *const_temp;
char *out;
size_t name_len;
size_t ct_len;
size_t total_len;
const_temp = luaL_tolstring(c->L, -1, NULL);
if (const_temp == NULL) {
cleanup_stack(c->L);
return NULL;
}
name_len = (c->name==NULL)?0:strlen(c->name);
ct_len = strlen(const_temp);
total_len = name_len+ct_len+2+1;
out = malloc(sizeof(*out)+total_len);
if (name_len > 0)
memcpy(out, c->name, name_len);
out[name_len] = '(';
memcpy(out+name_len+1, const_temp, ct_len);
out[name_len+1+ct_len] = ')';
out[total_len-1] = '\0';
cleanup_stack(c->L);
return out;
}
The Wrapper Explained
Wrapped Object Creation
The counter_create
function is the heart of the wrapper. It creates a Lua
state, opens the embedded module, creates a counter object, and returns a
wrapped counter object. Each time counter_create
is called a Lua state is
created.
Meaning that each counter object will be independent from one another. If you need to use multiple Lua objects that interact with one anther you’ll need to marshal data between each object via accessors provided by the wrappers. This might not be the easiest way to handle this situation but it keeps everything clearly separated and defined.
When calling the Lua counter module to get a counter object you’ll see that the
new function isn’t called directly. Instead the module itself is called, which
in turn calls new due to the __call
metatable function being linked to new.
This makes construction a bit simpler.
The Wrapped Functionality Functions
All of the wrapped functions use the same basic concepts. These are nearly
identical and ensure that the internal lua_State
(stack) always has the
counter object as the only item on the stack after each function call
regardless of success or failure. This is very import because if we don’t keep
the stack in a known state we won’t be able to call the object’s functions.
In this example the wrapped functions end up being more complex than what they wrap. Even if the functionality had been written in C the wrapper is still more complex. That’s something that needs to be considered if you plan to use an existing Lua module in this manner.
Lua C Function Failure and Application Termination
One thing to note is some of the Lua C functions can fail and cause a longjmp out of the current function. If this happens the application will terminate because the default error handler in these cases causes the application to abort/terminate. This situation is should only happen in very rare and drastic situations such as being out of memory. Due to these situations being nearly unrecoverable I’m ignoring them.
Letting the application terminate may not be the feasible. Luckily are a few ways to deal this situation.
Lua provides a number of safe functions which will return an error code instead
of calling longjmp. It is possible to push the C function you need to call onto
the stack using lua_pushcfunction
. Push the function’s arguments then call it
with lua_pcall
. lua_pcall
is one of those safe functions which returns an
error code.
Another method is to register a panic function using lua_atpanic immediately after creating the Lua state. The application will only abort if the panic function returns. Meaning if you longjmp to another point in your application you can recover and not abort. That said, this may not be useful especially during out of memory situations.
The final method I’ve found for handling these (admittedly rare situations) is
to use C++. Lua will use C++’s exceptions instead of longjmp
if using lua.hpp
and compiled into a C++ application. This means you can wrap any code blocks
that have Lua function calls in a try/catch block.
Example application
Here is a simple C application that uses the C wrapper. This application will create two counter objects to demonstrate that they are independent and the functioning of one will not impact the other.
main.c
#include <stdlib.h>
#include <stdio.h>
#include "counter.h"
int main(int argc, char **argv)
{
counter_t *c;
counter_t *d;
char *s;
c = counter_create(0, "c1");
d = counter_create(10, "d");
counter_add(c, 4);
counter_decrement(c);
counter_increment(d);
printf("val=%dn", counter_getval(c));
counter_subtract(c, -2);
counter_increment(c);
s = counter_tostring(c);
printf("%sn", s);
free(s);
s = counter_tostring(d);
printf("%sn", s);
free(s);
counter_destroy(c);
counter_destroy(d);
return 0;
}
Building and Running
CMakeLists.txt
cmake_minimum_required (VERSION 3.0)
project (lua_ccounter C)
find_package(Lua REQUIRED)
include_directories (
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${LUA_INCLUDE_DIR}
)
set (SOURCES
main.c
counter.c
)
add_executable (${PROJECT_NAME} ${SOURCES} ${LUA_LIBRARIES})
target_link_libraries (${PROJECT_NAME} lua)
Build and run:
$ luac -o counter_lua counter.lu
$ xxd -i counter_lua counter_lua.h
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./lua_ccounter
val=3
c1(6)
d(11)
As we can see the values of c1 is 3 and 6; d is 11. This is exactly what they should be.
The generated embed Lua library header
For completeness here is the counter_lua.h file that includes the compiled Lua counter module chunk.
counter_lua.h
unsigned char counter_lua[] = {
0x1b, 0x4c, 0x75, 0x61, 0x52, 0x00, 0x01, 0x04, 0x08, 0x04, 0x08, 0x00,
0x19, 0x93, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x06, 0x1b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
0x00, 0x4b, 0x80, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x4a, 0x80, 0x00,
0x80, 0x4a, 0x00, 0x80, 0x80, 0xa5, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x00,
0x81, 0x86, 0xc0, 0x40, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x00,
0x00, 0x47, 0x81, 0x40, 0x00, 0x0a, 0x41, 0x01, 0x82, 0x9d, 0x40, 0x80,
0x01, 0xa5, 0x40, 0x00, 0x00, 0x0a, 0x80, 0x80, 0x82, 0xa5, 0x80, 0x00,
0x00, 0x0a, 0x80, 0x00, 0x83, 0xa5, 0xc0, 0x00, 0x00, 0x0a, 0x80, 0x80,
0x83, 0xa5, 0x00, 0x01, 0x00, 0x0a, 0x80, 0x00, 0x84, 0xa5, 0x40, 0x01,
0x00, 0x0a, 0x80, 0x80, 0x84, 0xa5, 0x80, 0x01, 0x00, 0x4a, 0x80, 0x00,
0x85, 0x1f, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x80, 0x00, 0x0b, 0x00, 0x00,
0x00, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f,
0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x04, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x69, 0x6e, 0x64,
0x65, 0x78, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6e, 0x65, 0x77, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f,
0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x73, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74,
0x00, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e,
0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x04, 0x0a, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x63, 0x72, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x67, 0x65, 0x74, 0x76, 0x61, 0x6c, 0x00, 0x04, 0x0b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x85, 0x00,
0x00, 0x00, 0x58, 0x80, 0x00, 0x00, 0x17, 0x80, 0x00, 0x80, 0x84, 0x00,
0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x80, 0x01, 0x86, 0x40,
0xc0, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x01, 0x9d, 0x80,
0x80, 0x01, 0x8a, 0x40, 0x00, 0x81, 0x9f, 0x00, 0x00, 0x01, 0x1f, 0x00,
0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67,
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62,
0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74,
0x61, 0x62, 0x6c, 0x65, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0d,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x65, 0x72, 0x2e, 0x6c, 0x75, 0x61, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f,
0x00, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x45, 0x4e, 0x56, 0x00,
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x5f, 0x6d, 0x74,
0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03,
0x04, 0x00, 0x00, 0x00, 0x87, 0x00, 0x40, 0x00, 0x8d, 0x40, 0x00, 0x01,
0x0a, 0x80, 0x00, 0x80, 0x1f, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00,
0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x65, 0x72, 0x2e, 0x6c, 0x75, 0x61, 0x00, 0x04, 0x00, 0x00,
0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6c, 0x66, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00,
0x87, 0x00, 0x40, 0x00, 0x8e, 0x40, 0x00, 0x01, 0x0a, 0x80, 0x00, 0x80,
0x1f, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
0x2e, 0x6c, 0x75, 0x61, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x73, 0x65, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x6d,
0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00,
0x00, 0x01, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x40, 0x00,
0xc1, 0x40, 0x00, 0x00, 0x5d, 0x40, 0x80, 0x01, 0x1f, 0x00, 0x80, 0x00,
0x02, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x61, 0x64, 0x64, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x65, 0x72, 0x2e, 0x6c, 0x75, 0x61, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x73, 0x65, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x4c,
0x00, 0x40, 0x00, 0xc1, 0x40, 0x00, 0x00, 0x5d, 0x40, 0x80, 0x01, 0x1f,
0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x73, 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74,
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x6c,
0x75, 0x61, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c,
0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
0x65, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x01, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x5f,
0x00, 0x00, 0x01, 0x1f, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x65, 0x72, 0x2e, 0x6c, 0x75, 0x61, 0x00, 0x03, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x73, 0x65, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00,
0x00, 0x01, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x46, 0x00, 0x40, 0x00,
0x47, 0x40, 0xc0, 0x00, 0x81, 0x80, 0x00, 0x00, 0xc7, 0xc0, 0x40, 0x00,
0x5e, 0x00, 0x80, 0x01, 0x5f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x00,
0x04, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x04, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x00,
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x00,
0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x6c, 0x75, 0x61, 0x00, 0x07,
0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24,
0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24,
0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6c, 0x66, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x45, 0x4e, 0x56,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x2e,
0x6c, 0x75, 0x61, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x1d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x01, 0x00,
0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x4d, 0x5f, 0x6d, 0x74, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1b,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x5f, 0x45, 0x4e, 0x56, 0x00
};
unsigned int counter_lua_len = 1796;