Skip to content
Dustin Sallings edited this page Jan 12, 2011 · 14 revisions

LaBrea API

In addition to almost anything you can do in lua, you have a few features made available to you via labrea itself:

labrea.atexit

Registers a function to be invoked at program termination.

Example:

-- Total number of bytes read by the application.
total = 0

function after_read(rv, ...)
    total = total + rv
end

labrea.atexit(function()
                 io.stderr:write(string.format("Read %d bytes\n", total))
              end)

labrea.fileno

Returns the file descriptor ID for a FILE* object.

Example:

function after_fopen(rv, path, ...)
    io.stderr:write(string.format("File descriptor for '%s' is %d\n",
                                  labrea.tostring(path), labrea.fileno(rv)))
end

labrea.free

Free a temporary C buffer returned from labrea.malloc.

Example:

local x = labrea.malloc(16)
labrea.free(x)

labrea.invoke

When writing an around_wrapper, this allows you invoke the original function that was being called.

Example:

function around_read(f, fd, buf, size)
    return labrea.invoke(f, fd, buf, size)
end

labrea.malloc

Allocate a temporary buffer in C that can be used for whatever you might want.

Example:

local x = labrea.malloc(16)
labrea.free(x)

labrea.memcpy

Copy the contents of a string to a location in C.

-- Schrodinger's cat is dead half the time.
msg = "the cat is dead\n\\0"

function around_read(f, fd, buf, bytes)
   local rv = labrea.invoke(f, fd, buf, bytes)
   if rv > #msg and math.random(1, 100) < 50 then
      rv = #msg
      labrea.memcpy(buf, msg, rv)
   end
   return rv
end

labrea.periodic

Invoke a function periodically.

Example:

labrea.periodic(5, function()
                     io.stderr:write("It's been five seconds!\n")
                   end)

labrea.reinit

Instructs labrea to reinitialize the script mappings for all overridden functions.

You'd use this when your function made changes to the scripting envrionment as a whole, such as loading a new library at runtime that changes all of your bindings.

Example:

function after_listen(...)
    dofile("/some/path/started_listening.lua")
    labrea.reinit()
end

labrea.schedule

Schedule a function to run at some point in the future.

Example:

labrea.schedule(5, function()
                      io.stderr:write("Five seconds later!\n")
                   end)

labrea.set_errno

Here, you can adjust the errno value so your errors become meaningful.

Example:

function around_write(f, fd, buf, size)
    set_errno(28) -- ENOSPC
    return -1
end

labrea.tostring

Converts a pointer to a string.

You are expected to know whether the string is null-terminated (one-argument variant) or a fixed length (two-argument variant).

Example (null-terminated string):

function before_open(path, ...)
    io.stderr:write(string.format("Opening '%s'\n", labrea.tostring(path)))
end

Example (fixed-size buffer):

function after_read(rv, fd, buf, ...)
   local s = labrea.tostring(buf , rv)
   io.stderr:write(string.format("Lua saw %d bytes: ``%s''\n", rv, s))
end

labrea.usleep

This allows you to pause the execution of the calling thread by the given number of microseconds. This is useful to, for example, slow down a seek operation.

Example:

function before_lseek(...)
    labrea.usleep(500000) -- Sleep half a second
end