Wrapping a Lua module in C

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 = { __metatable = {}, __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=%d\n", counter_getval(c));

    counter_subtract(c, -2);
    counter_increment(c);

    s = counter_tostring(c);
    printf("%s\n", s);
    free(s);

    s = counter_tostring(d);
    printf("%s\n", 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;