lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Here is some info about wrapping Lua functions.  It seems to validate the
general usefulness of the expand function I outlined in a previous post
"vararg asymmetry".  No chance of having that added to baselib?

Given a function, I'd like to wrap it inside some pre and post-processing.
This is often useful for debugging or synchronization.  Here is a simple
example wrapping the global sin function:

    function sin(x)
        pre_function()
        local y = %sin(x)
        post_function()
        return y
    end

However this is not very general.  It would be nice to wrap functions
without knowing the details of their inputs and outputs.  Furthermore Lua
functions may have a variable number of  inputs or outputs (for example,
strfind).

Accounting for this, pre-processing is no problem.  Here I'm wrapping an
arbitrary global function X:

    function X(...)
        pre_function()
        return call(%X, arg)
    end

But what about the post-processing?  We need a way to temporarily store all
the return values of the wrapped function.  The only option seems to be to
store them in a table.  Here's a convenient function for that:

    function compress(...)
        return arg
    end

That was easy, but we'll also need an expand function to convert the table
back into individual return values.  Such a function was the topic of my
"vararg asymmetry" post.  It can be implemented recursively in Lua or
iteratively using the C API.  Using these functions, here is the final
version of the function wrapping:

    function X(...)

        pre_function()
        local results = compress(call(%X, arg))
        post_function()
        return expand(results)
    end

If this all seems esoteric, here is a practical example.  I'd like to wrap
dofile and have it load relative to the current script, whose path is held
in a variable SCRIPT_NAME.  It handles recursive calls by saving and
restoring the path:

    function dofile(name)
        local temp = SCRIPT_NAME
        SCRIPT_NAME = DirectoryPart(SCRIPT_NAME).."/"..name
        local results = compress(%dofile(SCRIPT_NAME))

        SCRIPT_NAME = temp
        return expand(results)
    end

-John