[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: Direct accessing of application variables from lua
- From: Falko Poiker <fpoiker@...>
- Date: Tue, 9 May 2000 18:03:51 -0700
> >From: Falko Poiker <fpoiker@relic.com>
> >The other reason I don't want to use tolua, and this seems to be a
problem
> >with lua in general, is that it creates wrapper functions for every
variable
> >and object/structure element accessed by lua.
> No really. You only need to create wrapper functions for each *type*.
> Variables are exported to Lua as userdata, and variables of the same type
> have the same tag, so that they can share the get/setglobal tag methods.
> This is exactly what tolua does.
Hmmm... That doesn't seem to be what I'm experiencing. I have a large
number of variables in my tolua.pkg file, and tolua creates a
toluaI_set_<varname> and a toluaI_get_<varname> function for every one,
whether the variable is a float, int or a user defined type (in the example
below, the vector4 class).
> If you need concrete examples of how to do all this, post some
> declarations of your variables and I'll send you some sample code.
Okay, in my tolua.pkg file I have (among other things) the following:
class vector4 {
float x;
float y;
float z;
float w;
vector4() {}
vector4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z =
_z; w = _w; }
void set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z =
_z; w = _w; }
// some other methods
}
/*==========================================================================
===
Pieplate tweakables:
============================================================================
=*/
extern int twkPiePieces;
extern int twkHorizonPieces;
extern real32 twkPieClosestDistance;
extern real32 twkMaxMovementDist;
extern real32 twkHorizontalHashMarkLength;
extern real32 twkVerticalHashMarkLength;
extern real32 twkHeightSnap;
extern real32 twkShipCloseToPlaneDistance;
extern real32 twkPieCircleSizeMax;
extern real32 twkPieCircleSizeMin;
extern real32 twkHeightFactor;
extern vector4 test;
extern vector4 twkInnerPieColour;
extern vector4 twkRangePieColour;
extern vector4 twkOuterPieColour;
extern vector4 twkMoveToDiscColour;
extern vector4 twkMoveToPlanarDiscColour;
extern vector4 twkShipOnPlaneColour;
extern vector4 twkClosestShipOnPlaneColour;
This package file creates 2 functions for every variable (registered
internally to tolua using the functions calls "tolua_tablevar" and
"tolua_globalvar"). For example, for the "test" variable, the
tolua_XXX_open function has the line
tolua_globalvar("test",toluaI_get_test,toluaI_set_test);
and the functions
/* get function: test */
static void toluaI_get_test(void)
{
tolua_pushusertype((void*)&test,tolua_tag_vector4);
}
/* set function: test */
static void toluaI_set_test(void)
{
if (!tolua_istype(1,tolua_tag_vector4,0))
tolua_error("#vinvalid type in variable assignment.");
test = *((vector4*) tolua_getusertype(1,0));
}
> >Homeworld (our last game) had
> >over 10,000 tweakables, so exposing this number of variables to lua would
> >result in over 1 megabyte of memory usage simply for the function
wrappers.
> Do you really have 10,000 different *types*?
No, 10,000 different variables. Very few types - most are real, int, char
or vector.
> >So I've been considering another option - modifying the lua code so that
it
> >modifies the game variables directly.
> You could do this of course, although I don't see you can avoid having
several
> types in the Value union.
> >1. there is no need to pre-register any of the game's variables with Lua
-
> >the variables are accessed on a "need to know" basis.
> Again, I don't see you can avoid this.
Well, I've been poking around a bit, and here's a code snippet of what it
would look like:
// From lvm.c of version 3.2
void luaV_setglobal (TaggedString *ts) {
// Falko's modification
//was: TObject *oldvalue = &ts->u.s.globalval;
TObject *oldvalue = getGameGlobal(ts->str, &ts->u.s.globalval);
TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
if (ttype(im) == LUA_T_NIL) /* is there a tag method? */
{
// added by Falko
setGameGlobal(ts->str, L->stack.top->value.n);
luaS_rawsetglobal(ts, --L->stack.top);
}
else {
/* WARNING: caller must assure stack space */
struct Stack *S = &L->stack;
TObject newvalue;
newvalue = *(S->top-1);
ttype(S->top-1) = LUA_T_STRING;
tsvalue(S->top-1) = ts;
*S->top++ = *oldvalue;
*S->top++ = newvalue;
luaD_callTM(im, 3, 0);
}
}
getGameGlobal compares "ts->str" with its internal list of variable names -
if it finds a game variable of the same name, it creates a "TObject" with
the correct value and returns it, if not, it returns
"&ts->u.s.globalval".
setGameGlobal does the same, but sets the game variable and returns nothing.
Note that the number parameter of setGameGlobal (L->stack.top->value.n) is
only temporary. I imagine that "setGameGlobal" would accept the value enum
directly and extract what it needs in C.
Later iterations of getGameGlobal and setGameGlobal would somehow get around
doing a string compare every time by creating a pointer to any variable
accessed to create a shortcut to that variable (possibly by defining a "game
variable" type in the Value union or something like that).
By the way, I'm only suggesting doing this because I thought I could
eliminate a bunch of work on my part. If Lua provides a mechanism to do
this easily without modifying the lua code, I would be very pleased to know
how.
Thanks for your help!!
Falko