The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdio.h>
#include "ppport.h"
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#if LUA_VERSION_NUM < 501
#error "This requires at least version 5.1 of Lua"
#endif
#include "const-c.inc"
#define MY_CXT_KEY "Lua::API::_guts" XS_VERSION
typedef struct {
HV *OOB;
} my_cxt_t;
START_MY_CXT
/*-------------------------------------------------------------------*/
/* Support for out-of-band data
Lua interfaces to C functions, not Perl ones, and they must be
declared at compile time (can't create them on the fly) so we
use trampoline C functions to call Perl. Sometimes its possible
to attach routing information (via Lua C closures) so that the
trampoline knows which Perl function to call. Sometimes its not.
In the latter case, for certain classes of uses (such as hooks) we
can deduce which Perl function to call based upon some extra piece
of data needs to be stored somewhere. This provides that facility.
We keep track of the out-of-band data in a Perl hash, keyed off of
a pointer address (like an inside-out object). We could
have created a LuaInterpreter Object which contains both the
lua_State pointer and any other instance specific data, but that
makes using the automated XS calling of Lua functions much more
messy.
*/
/* The OOB hash stores data keyed off of a pointer. Its values are
hashes */
static
HV* get_oob_entry( void *ptr )
{
dMY_CXT;
HV* oob;
{
SV ** svp = hv_fetch( MY_CXT.OOB, (const char*) &ptr, sizeof(ptr), 1 );
if ( svp == NULL )
croak( "Perl Lua::API: error getting OOB hash\n" );
/* if not defined, has not yet been created; do so */
if ( ! SvOK( *svp) )
{
HV *t_hv = newHV();
SV *t_rv = newRV_inc( (SV*) t_hv );
svp = hv_store( MY_CXT.OOB, (const char*) &ptr, sizeof(ptr), t_rv, 0);
}
oob = (HV*) SvRV(*svp);
if ( SVt_PVHV != SvTYPE(oob) )
croak( "Perl Lua::API: OOB entry %p is not a hash\n", (void *) ptr );
}
return oob;
}
static
SV * delete_oob_entry( void *ptr )
{
dMY_CXT;
return hv_delete( MY_CXT.OOB, (const char*) &ptr, sizeof(ptr), 0 );
}
/*-------------------------------------------------------------------*/
/* Mapping lua_State* to Lua::API::State objects
When Lua calls the trampolines, its passes in a lua_State*. Perl,
however, wants a Lua::API::State object. We could create them on the
fly from the lua_State* (since there's nothing in the Lua::API::State
object but a lua_State*), but then Lua::API::State::DESTROY would get
called whenever the temporary objects are destroyed, which
is not good.
Instead, we keep track of the original Lua::API::State object in the OOB
hash.
*/
static
SV* get_Perl_object( void *ptr )
{
SV** svp = hv_fetch( get_oob_entry( ptr ), "object", 5, 0 );
if ( svp == NULL )
croak( "Perl Lua::API::get_Perl_object: error getting object\n" );
return *svp;
}
static
void set_Perl_object( void *ptr, SV* object )
{
HV* oob = get_oob_entry( ptr );
/* store Perl Lua::API::State object keyed off of lua_State pointer */
SV** svp = hv_fetch( oob, "object", 5, 1 );
if ( svp == NULL )
croak( "Perl Lua::API::set_Perl_object: error getting object\n" );
sv_setsv( *svp, object );
}
#if 0
/*-------------------------------------------------------------------*/
/* panic function to catch errors thrown from Lua API calls. This is
used to turn them into Perl exceptions */
static
int set_panic( lua_State *L, jump_buf *env)
{
HV* oob = get_oob_entry( L );
SV** svp = hv_fetch(oob, "panic", 5, 1 );
if ( svp == NULL )
croak( "Perl Lua::API: error getting panic state\n" );
if ( env )
{
sv_setpvn( *svp, env, sizeof(*env) );
}
else
{
hv_delete( oob, "panic", 4, G_DISCARD );
}
}
static
int panic( Lua_State *L )
{
HV* oob = get_oob_entry( L );
SV** svp = hv_fetch(oob, "panic", 5, 1 );
if ( svp == NULL )
croak( "Perl Lua::API: error getting panic state\n" );
}
#endif
/*-------------------------------------------------------------------*/
/* Support for hooks */
static
void set_hook( lua_State *L, SV* func )
{
HV* oob = get_oob_entry( L );
SV** svp = hv_fetch( oob, "hook", 4, 1 );
if ( svp == NULL )
croak( "Perl Lua::API: error getting hook\n" );
if ( SvOK(func) )
{
sv_setsv( *svp, func );
}
else
{
hv_delete( oob, "hook", 4, G_DISCARD );
}
}
/* trampoline */
static
void l2p_hook( lua_State *L, lua_Debug *ar )
{
char *error = NULL;
STRLEN error_len;
SV** svp;
HV* oob = get_oob_entry( L );
SV* hook;
dSP;
svp = hv_fetch( oob, "hook", 4, 0 );
if ( svp == NULL )
croak( "Perl Lua::API: error getting hook\n" );
hook = *svp;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(get_Perl_object(L));
XPUSHs(get_Perl_object(ar));
PUTBACK;
call_sv( hook, G_EVAL | G_DISCARD );
SPAGAIN;
/* catch exceptions */
if (SvTRUE(ERRSV))
{
POPs;
error = SvPV( ERRSV, error_len );
/* If this is an exception thrown by Lua::API::State::error(),
everything is already on the Lua stack and nothing further
needs to be done. If not, need to set up stack.
*/
if ( ! sv_isa( ERRSV, "Lua::API::State::Error" ) )
lua_pushstring( L, error );
}
PUTBACK;
FREETMPS;
LEAVE;
if ( error )
lua_error( L );
}
/*-------------------------------------------------------------------*/
/* Support for pushcfunction and pushcclosure.
*
* The SV pointer is stored as the *last* upvalue for the trampoline
* routine. Perl routines which use lua_Debug.nups to get the number
* of upvalues must decrement it by one to get their true upvalue
* count.
*
*/
static
int l2p_closure( lua_State *L )
{
dSP;
SV *func;
char *error = NULL;
STRLEN error_len;
int count;
lua_Debug ar;
lua_getstack( L, 0, &ar );
lua_getinfo( L, "u", &ar );
func = (SV*) lua_touserdata( L, lua_upvalueindex( ar.nups ) );
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(get_Perl_object(L));
PUTBACK;
count = call_sv( func, G_EVAL | G_SCALAR);
/* catch exceptions */
if (SvTRUE(ERRSV))
{
POPs;
error = SvPV( ERRSV, error_len );
/* If this is an exception thrown by Lua::API::State::error(),
everything is already on the Lua stack and nothing further
needs to be done. If not, need to set up stack.
*/
if ( ! sv_isa( ERRSV, "Lua::API::State::Error" ) )
lua_pushstring( L, error );
}
PUTBACK;
FREETMPS;
LEAVE;
if ( error )
lua_error( L );
return count;
}
/*-------------------------------------------------------------------*/
/* Support for lua_cpcall.
*
* lua_cpcall calls a C function directly with a lightuserdata value
* on the stack. We can't use a closure to wrap the Perl SV, so, we
* wrap it explicitly in a structure. This is the trampoline routine
* which unwraps it and calls the Perl routine
*
*/
typedef struct {
SV *sv; /* Perl function to call */
void *ud; /* user data pointer */
} CPCallData;
static
int l2p_cpcall( lua_State *L ) {
dSP;
int count;
char *error = NULL;
STRLEN error_len;
CPCallData *data;
/* grab our structure... */
data = (CPCallData *) lua_touserdata( L, -1 );
/* ...remove it from the stack */
lua_pop( L, 1 );
/* ...and replace it with the user data */
lua_pushlightuserdata( L, data->ud );
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(get_Perl_object(L));
PUTBACK;
count = call_sv( (SV*) data->sv, G_EVAL | G_DISCARD);
SPAGAIN;
/* catch exceptions */
if (SvTRUE(ERRSV))
{
POPs;
error = SvPV( ERRSV, error_len );
/* If this is an exception thrown by Lua::API::State::error(),
everything is already on the Lua stack and nothing further
needs to be done. If not, need to set up stack.
*/
if ( ! sv_isa( ERRSV, "Lua::API::State::Error" ) )
lua_pushstring( L, error );
}
PUTBACK;
FREETMPS;
LEAVE;
if ( error )
lua_error( L );
return count;
}
/*-------------------------------------------------------------------*/
/* put Lua error object on stack using lua_error. call only from XS
routines. */
static int
call_lua_error( lua_State *L )
{
return lua_error( L );
}
static void
throw_lua_error( lua_State *L, char *error )
{
lua_pushcfunction( L, &call_lua_error );
lua_pushstring(L, error );
lua_pcall( L, 1, 0, 0 );
}
/* based on code in lauxlib.c */
static void
throw_luaL_error( lua_State *L, const char *fmt, ... )
{
lua_pushcfunction( L, &call_lua_error );
va_list argp;
va_start(argp, fmt);
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
va_end(argp);
lua_concat(L, 2);
lua_pcall( L, 1, 0, 0 );
}
/*-------------------------------------------------------------------*/
#include "wrap.h"
/*-------------------------------------------------------------------*/
MODULE = Lua::API PACKAGE = Lua::API
INCLUDE: const-xs.inc
BOOT:
{
MY_CXT_INIT;
MY_CXT.OOB = newHV();
}
# oh, ick
const char *
RELEASE( )
CODE:
RETVAL = LUA_RELEASE;
OUTPUT:
RETVAL
const char *
COPYRIGHT( )
CODE :
RETVAL = LUA_COPYRIGHT;
OUTPUT:
RETVAL
MODULE = Lua::API PACKAGE = Lua::API::State PREFIX = lua_
lua_CFunction
lua_atpanic(L, panicf)
lua_State * L
lua_CFunction panicf
void
lua_call(L, nargs, nresults)
lua_State * L
int nargs
int nresults
# call either lua_checkstack or luaL_checkstack based upon the number
# of parameters
void
lua_checkstack(L, sz, ...)
lua_State * L
int sz
PPCODE:
/* call lua_checkstack */
if ( items == 2 )
{
int status = lua_checkstack( L, sz );
EXTEND(SP, 1);
PUSHs(sv_2mortal(newSViv(status)));
}
/* emulate luaL_checkstack */
else if ( items == 3 )
{
const char *msg = (const char*) SvPV_nolen(ST(2));
if ( !lua_checkstack( L, sz ) )
{
throw_luaL_error( L, "stack overflow (%s)", msg );
SV *rv = newSV(0);
SV *sv = newSVrv( rv, "Lua::API::State::Error" );
sv_setsv((SV*) get_sv("@", GV_ADD), rv);
croak(NULL);
}
}
else
{
croak_xs_usage( cv, "L,sz,[msg]" );
}
# void
# lua_close(L)
# lua_State * L
void
lua_concat(L, n)
lua_State * L
int n
int
lua_cpcall(L, func, ud)
lua_State * L
SV *func
SV *ud
PREINIT:
CPCallData data = { func, ud };
CODE:
RETVAL = lua_cpcall( L, l2p_cpcall, &data );
OUTPUT:
RETVAL
void
lua_createtable(L, narr, nrec)
lua_State * L
int narr
int nrec
# No support for lua_Writer
# int
# lua_dump(L, writer, data)
# lua_State * L
# lua_Writer writer
# void * data
#
int
lua_equal(L, idx1, idx2)
lua_State * L
int idx1
int idx2
int
lua_gc(L, what, data)
lua_State * L
int what
int data
lua_Alloc
lua_getallocf(L, ud)
lua_State * L
void ** ud
void
lua_getfenv(L, idx)
lua_State * L
int idx
void
lua_getfield(L, idx, k)
lua_State * L
int idx
const char * k
int
lua_getgccount(L)
lua_State * L
void
lua_getglobal(L, name)
lua_State * L
const char * name
lua_Hook
lua_gethook(L)
lua_State * L
int
lua_gethookcount(L)
lua_State * L
int
lua_gethookmask(L)
lua_State * L
int
lua_getinfo(L, what, ar)
lua_State * L
const char * what
lua_Debug * ar
const char *
lua_getlocal(L, ar, n)
lua_State * L
const lua_Debug * ar
int n
void
lua_getmetatable(L, ...)
lua_State * L
PPCODE:
if ( items != 1 )
croak_xs_usage( cv, "L,(objindex|name)" );
if ( looks_like_number( ST(1) ) )
{
int objindex = (int)SvIV(ST(1));
int RETVAL = lua_getmetatable(L, objindex);
EXTEND(SP,1);
PUSHs(sv_2mortal(newSViv(RETVAL)));
}
else
{
const char *n = (const char *)SvPV_nolen(ST(1));
luaL_getmetatable(L, n);
XSRETURN_EMPTY;
}
void
lua_getregistry(L)
lua_State * L
int
lua_getstack(L, level, ar)
lua_State * L
int level
lua_Debug * ar
void
lua_gettable(L, idx)
lua_State * L
int idx
int
lua_gettop(L)
lua_State * L
const char *
lua_getupvalue(L, funcindex, n)
lua_State * L
int funcindex
int n
void
lua_insert(L, idx)
lua_State * L
int idx
int
lua_isboolean(L, index)
lua_State * L
int index
int
lua_iscfunction(L, idx)
lua_State * L
int idx
int
lua_isfunction(L, index)
lua_State * L
int index
int
lua_islightuserdata(L, index)
lua_State * L
int index
int
lua_isnil(L, index)
lua_State * L
int index
int
lua_isnone(L, index)
lua_State * L
int index
int
lua_isnoneornil(L, index)
lua_State * L
int index
int
lua_isnumber(L, idx)
lua_State * L
int idx
int
lua_isstring(L, idx)
lua_State * L
int idx
int
lua_istable(L, index)
lua_State * L
int index
int
lua_isthread(L, index)
lua_State * L
int index
int
lua_isuserdata(L, idx)
lua_State * L
int idx
int
lua_lessthan(L, idx1, idx2)
lua_State * L
int idx1
int idx2
# No support for lua_Reader
# int
# lua_load(L, reader, dt, chunkname)
# lua_State * L
# lua_Reader reader
# void * dt
# const char * chunkname
# There is currently no support for setting another allocator.
# luaL_newstate() is used instead. If an allocator is ever
# supported, then newstate() should be written to accept either no
# arguments (and use luaL_newstate) or two (and use lua_newstate).
# lua_State *
# lua_newstate(f, ud)
# lua_Alloc f
# void * ud
void
lua_newtable(L)
lua_State * L
lua_State *
lua_newthread(L)
lua_State * L
void *
lua_newuserdata(L, sz)
lua_State * L
size_t sz
int
lua_next(L, idx)
lua_State * L
int idx
size_t
lua_objlen(L, idx)
lua_State * L
int idx
int
lua_pcall(L, nargs, nresults, errfunc)
lua_State * L
int nargs
int nresults
int errfunc
void
lua_pop(L, index)
lua_State * L
int index
void
lua_pushboolean(L, b)
lua_State * L
int b
void
lua_pushcclosure(L, fn, n)
lua_State * L
SV * fn
int n
PREINIT:
SV *sv_c = newSVsv(fn);
CODE:
lua_pushlightuserdata(L, sv_c );
lua_pushcclosure(L, l2p_closure, n+1 );
void
lua_pushcfunction(L, f)
lua_State * L
SV *f
PREINIT:
SV *sv_c = newSVsv(f);
CODE:
lua_pushlightuserdata(L, sv_c );
lua_pushcclosure(L, l2p_closure, 1 );
# This is (temporarily) in API.pm
# const char *
# lua_pushfstring(L, fmt, ...)
# lua_State * L
# const char * fmt
void
lua_pushinteger(L, n)
lua_State * L
lua_Integer n
void
lua_pushlightuserdata(L, p)
lua_State * L
void * p
void
lua_pushlstring(L, s, l)
lua_State * L
const char * s
size_t l
void
lua_pushliteral(L, s)
lua_State * L
const char * s
CODE:
lua_pushlstring(L,s,strlen(s));
void
lua_pushnil(L)
lua_State * L
void
lua_pushnumber(L, n)
lua_State * L
lua_Number n
void
lua_pushstring(L, s)
lua_State * L
const char * s
int
lua_pushthread(L)
lua_State * L
void
lua_pushvalue(L, idx)
lua_State * L
int idx
# This is (temporarily) in Lua/API.pm
# const char *
# lua_pushvfstring(L, fmt, argp)
# lua_State * L
# const char * fmt
# va_list argp
int
lua_rawequal(L, idx1, idx2)
lua_State * L
int idx1
int idx2
void
lua_rawget(L, idx)
lua_State * L
int idx
void
lua_rawgeti(L, idx, n)
lua_State * L
int idx
int n
void
lua_rawset(L, idx)
lua_State * L
int idx
void
lua_rawseti(L, idx, n)
lua_State * L
int idx
int n
void
lua_remove(L, idx)
lua_State * L
int idx
void
lua_replace(L, idx)
lua_State * L
int idx
int
lua_resume(L, narg)
lua_State * L
int narg
# There is currently no support for setting another allocator.
# void
# lua_setallocf(L, f, ud)
# lua_State * L
# lua_Alloc f
# void * ud
int
lua_setfenv(L, idx)
lua_State * L
int idx
void
lua_setfield(L, idx, k)
lua_State * L
int idx
const char * k
void
lua_setglobal(L, s)
lua_State * L
const char * s
int
lua_sethook(L, func, mask, count)
lua_State * L
SV *func
int mask
int count
CODE:
set_hook( L, func );
RETVAL = lua_sethook( L, SvOK(func) ? l2p_hook : NULL, mask, count );
void
lua_setlevel(from, to)
lua_State * from
lua_State * to
const char *
lua_setlocal(L, ar, n)
lua_State * L
const lua_Debug * ar
int n
int
lua_setmetatable(L, objindex)
lua_State * L
int objindex
void
lua_settable(L, idx)
lua_State * L
int idx
void
lua_settop(L, idx)
lua_State * L
int idx
const char *
lua_setupvalue(L, funcindex, n)
lua_State * L
int funcindex
int n
int
lua_status(L)
lua_State * L
size_t
lua_strlen(L, index)
lua_State * L
int index
int
lua_toboolean(L, idx)
lua_State * L
int idx
lua_CFunction
lua_tocfunction(L, idx)
lua_State * L
int idx
lua_Integer
lua_tointeger(L, idx)
lua_State * L
int idx
const char *
lua_tolstring(L, idx, len)
lua_State * L
int idx
size_t &len
lua_Number
lua_tonumber(L, idx)
lua_State * L
int idx
const void *
lua_topointer(L, idx)
lua_State * L
int idx
const char *
lua_tostring(L, index)
lua_State * L
int index
lua_State *
lua_tothread(L, idx)
lua_State * L
int idx
SV *
lua_touserdata(L, idx)
lua_State * L
int idx
int
lua_type(L, idx)
lua_State * L
int idx
const char *
lua_typename(L, tp)
lua_State * L
int tp
void
lua_xmove(from, to, n)
lua_State * from
lua_State * to
int n
int
lua_yield(L, nresults)
lua_State * L
int nresults
int
luaopen_base(L)
lua_State * L
int
luaopen_debug(L)
lua_State * L
int
luaopen_io(L)
lua_State * L
int
luaopen_math(L)
lua_State * L
int
luaopen_os(L)
lua_State * L
int
luaopen_package(L)
lua_State * L
int
luaopen_string(L)
lua_State * L
int
luaopen_table(L)
lua_State * L
MODULE = Lua::API PACKAGE = Lua::API::State PREFIX = luaL_
INCLUDE: xs.h
void
luaL_openlibs(L)
lua_State * L
void
luaL_buffinit(L, B)
lua_State * L
luaL_Buffer * B
int
luaL_callmeta(L, obj, e)
lua_State * L
int obj
const char * e
int
luaL_dofile(L, fn)
lua_State * L
const char * fn
int
luaL_dostring(L, s)
lua_State * L
const char * s
# implemented in Lua/API.pm
# int
# luaL_error(L, fmt, ...)
# lua_State * L
# const char * fmt
const char *
luaL_findtable(L, idx, fname, szhint)
lua_State * L
int idx
const char * fname
int szhint
int
luaL_getmetafield(L, obj, e)
lua_State * L
int obj
const char * e
const char *
luaL_gsub(L, s, p, r)
lua_State * L
const char * s
const char * p
const char * r
int
luaL_loadbuffer(L, buff, sz, name)
lua_State * L
const char * buff
size_t sz
const char * name
int
luaL_loadfile(L, filename)
lua_State * L
const char * filename
int
luaL_loadstring(L, s)
lua_State * L
const char * s
int
luaL_newmetatable(L, tname)
lua_State * L
const char * tname
lua_State *
luaL_newstate(CLASS)
char *CLASS = NO_INIT
PROTOTYPE: $
ALIAS:
open = 1
new = 2
PPCODE:
RETVAL = luaL_newstate();
ST(0) = sv_newmortal();
sv_setref_iv(ST(0), "Lua::API::State", PTR2IV(RETVAL));
set_Perl_object( RETVAL, ST(0) );
XSRETURN(1);
int
luaL_ref(L, t)
lua_State * L
int t
# implemented in Lua/API.pm
# void
# luaL_register(L, libname, l)
# lua_State * L
# const char * libname
# const luaL_Reg * l
void
luaL_unref(L, t, ref)
lua_State * L
int t
int ref
void
luaL_where(L, lvl)
lua_State * L
int lvl
MODULE = Lua::API PACKAGE = Lua::API::State
void
DESTROY( lua_State * L )
ALIAS:
close = 1
CODE:
if ( NULL != delete_oob_entry( L ) )
lua_close( L );
# These functions are wrapped in Lua/API.pm, which calls them
# explicitly, so don't remove the prefix
int
lua_error(L)
lua_State * L
void
lua_register(L, name, f)
lua_State * L
const char * name
SV * f
PREINIT:
SV *sv_c = newSVsv(f);
CODE:
lua_pushlightuserdata(L, sv_c );
lua_pushcclosure(L, l2p_closure, 1 );
lua_setglobal(L, name );
int
lua_getmetatable(L, index)
lua_State * L
int index
void
luaL_getmetatable(L, n)
lua_State * L
const char * n
const char *
lua_typename(L, tp)
lua_State * L
int tp
const char *
luaL_typename(L, i)
lua_State * L
int i
MODULE = Lua::API PACKAGE = Lua::API::Debug
lua_Debug *
new(CLASS)
char *CLASS = NO_INIT
PROTOTYPE: $
PPCODE:
Newxz( RETVAL, 1, lua_Debug );
ST(0) = sv_newmortal();
sv_setref_iv(ST(0), "Lua::API::Debug", PTR2IV(RETVAL));
set_Perl_object( RETVAL, ST(0) );
XSRETURN(1);
void
DESTROY(THIS)
lua_Debug * THIS;
CODE:
delete_oob_entry( THIS );
Safefree(THIS);
int
event(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->event;
OUTPUT:
RETVAL
const char *
name(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->name;
OUTPUT:
RETVAL
const char *
namewhat(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->namewhat;
OUTPUT:
RETVAL
const char *
what(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->what;
OUTPUT:
RETVAL
const char *
source(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->source;
OUTPUT:
RETVAL
int
currentline(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->currentline;
OUTPUT:
RETVAL
int
nups(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->nups;
OUTPUT:
RETVAL
int
linedefined(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->linedefined;
OUTPUT:
RETVAL
int
lastlinedefined(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->lastlinedefined;
OUTPUT:
RETVAL
char *
short_src(THIS)
lua_Debug * THIS
PROTOTYPE: $
CODE:
RETVAL = THIS->short_src;
OUTPUT:
RETVAL
MODULE = Lua::API PACKAGE = Lua::API::Buffer PREFIX = luaL_
luaL_Buffer *
new(CLASS)
char *CLASS = NO_INIT
PROTOTYPE: $
PPCODE:
Newxz( RETVAL, 1, luaL_Buffer );
ST(0) = sv_newmortal();
sv_setref_iv(ST(0), "Lua::API::Buffer", PTR2IV(RETVAL));
set_Perl_object( RETVAL, ST(0) );
XSRETURN(1);
void
DESTROY(THIS)
luaL_Buffer * THIS;
CODE:
delete_oob_entry( THIS );
Safefree(THIS);
void
luaL_addchar(B, c)
luaL_Buffer * B
char c
void
luaL_addlstring(B, s, l)
luaL_Buffer * B
const char * s
size_t l
void
luaL_addsize(B, n)
luaL_Buffer * B
size_t n
void
luaL_addstring(B, s)
luaL_Buffer * B
const char * s
void
luaL_addvalue(B)
luaL_Buffer * B
char *
luaL_prepbuffer(B)
luaL_Buffer * B
void
luaL_pushresult(B)
luaL_Buffer * B