Simple Lua
Hi all,
I decided that scripting would be best for some things in my game.
MAN!, are there a lot of confusing Lua examples out there!
Essentially I just wish to load my script (luaL_loadfile) and then later (i.e not execute immediately) pass parameters into it.
What's confusing me is how to pass these params (tables, arg??), how do I call different functions within the same .lua script?
I see horrible examples with settable then gettable; stack adjustment.
All seems rather messy; and yet my requirement seems sooo simple! (or I thought so).
Only just started looking at Lua today; so perhaps I'm trying to run before I can crawl; but it shouldn't be that hard...
Any simple/clean/obvious code fragment or help appreciated!
Cheers
I decided that scripting would be best for some things in my game.
MAN!, are there a lot of confusing Lua examples out there!
Essentially I just wish to load my script (luaL_loadfile) and then later (i.e not execute immediately) pass parameters into it.
What's confusing me is how to pass these params (tables, arg??), how do I call different functions within the same .lua script?
I see horrible examples with settable then gettable; stack adjustment.
All seems rather messy; and yet my requirement seems sooo simple! (or I thought so).
Only just started looking at Lua today; so perhaps I'm trying to run before I can crawl; but it shouldn't be that hard...
Any simple/clean/obvious code fragment or help appreciated!
Cheers
http://onesadcookie.com/svn/SmileyTag/ may be of interest to you. You can see calling lua functions from C in STOpenGLView.m
Thanks!
I have managed to get something basically functional up now.
I presume the best thing to do is simply send a pointer into a Lua script that references everything that script could need? (i.e. efficient and flexible)
Cheers
EDIT: actually any help on pointer passing in might be useful as it seems like another "not really 1 method" area :-)
In C I have OBJECT *thing; I wish to pass 'thing' into Lua, alter any pointers off of that (e.g. thing->name).
All nicely :-) , can't see how lua deals with the -> indirection
EDIT 2: Ok, pushlightuserdata. But it doesn't know it's type (and why should it). Googling something about environment tables; but no examples (assuming thats the right thing!)
I have managed to get something basically functional up now.
I presume the best thing to do is simply send a pointer into a Lua script that references everything that script could need? (i.e. efficient and flexible)
Cheers
EDIT: actually any help on pointer passing in might be useful as it seems like another "not really 1 method" area :-)
In C I have OBJECT *thing; I wish to pass 'thing' into Lua, alter any pointers off of that (e.g. thing->name).
All nicely :-) , can't see how lua deals with the -> indirection
EDIT 2: Ok, pushlightuserdata. But it doesn't know it's type (and why should it). Googling something about environment tables; but no examples (assuming thats the right thing!)
OK!
I can see this isn't sooo simple!
SWIG,userdata,upvalues; erm um!; I just want to pass a pointer to a struct into Lua and access it 'normal' :-)))
Anyway!, my *fix* (I only need simple lua script processing) is to lua_register a C function.
Push to the stack the paramter I am interested in (e.g. "xpos") have the 'C' func pop that and then return the required value(s) back to Lua.
That's not nice!, but it's simple!
Cheers all
I can see this isn't sooo simple!
SWIG,userdata,upvalues; erm um!; I just want to pass a pointer to a struct into Lua and access it 'normal' :-)))
Anyway!, my *fix* (I only need simple lua script processing) is to lua_register a C function.
Push to the stack the paramter I am interested in (e.g. "xpos") have the 'C' func pop that and then return the required value(s) back to Lua.
That's not nice!, but it's simple!
Cheers all
OK!, I hate the way I do this in Lua (by probably not understanding it correctly).
But how the heck do you check in Lua for a null pointer
~=nil ~=NULL all seem to fail.
I hate 'alt + n' for tilde; I like != :-)))
Cheers
EDIT:
Why must I do this:
if (obj->collided_with!=NULL)
lua_pushlightuserdata(L, obj->collided_with);
else
lua_pushnumber(L,0);
and not just pass through the null pointer to lightuserdata
But how the heck do you check in Lua for a null pointer
~=nil ~=NULL all seem to fail.
I hate 'alt + n' for tilde; I like != :-)))
Cheers
EDIT:
Why must I do this:
if (obj->collided_with!=NULL)
lua_pushlightuserdata(L, obj->collided_with);
else
lua_pushnumber(L,0);
and not just pass through the null pointer to lightuserdata
tilde is shift-backtick on US keyboards/layouts...
if you wrap NULL in a light userdata you're screwed. lua nil != light userdata containing NULL
if you wrap NULL in a light userdata you're screwed. lua nil != light userdata containing NULL
Hey OSC!,
But why not?!?!?!????
My "hack" does the job, but it seems a bit pants!
In fact my whole "method" for accessing structures withint Lua is rather crappy:
if (!strcmp(str,"body->p.x"))
lua_pushnumber(L,obj->body->p.x);
if (!strcmp(str,"collided_with"))
{
if (obj->collided_with!=NULL)
lua_pushlightuserdata(L, obj->collided_with);
else
lua_pushnumber(L,0);
}
if (!strcmp(str,"type"))
lua_pushnumber(L,obj->type);
Lua sends the string to a C func; the c func pushes it on the stack.
Ok I could optimize to avoid the string comparison; but it's rather primitive and messy.
Again, I assume my lack of Lua knowledge is the main issue.
Looked at SWIG stuff; went EH!; and decided that was more trouble than it was worth.
Ho-hum!, crude method works- just feels rather cack when I spend lots of my time holding onto 60fps to have some crappy scripting to C interface be so poor.
Spank me if I am talking rubbish; I need it!
Cheers
But why not?!?!?!????
My "hack" does the job, but it seems a bit pants!
In fact my whole "method" for accessing structures withint Lua is rather crappy:
if (!strcmp(str,"body->p.x"))
lua_pushnumber(L,obj->body->p.x);
if (!strcmp(str,"collided_with"))
{
if (obj->collided_with!=NULL)
lua_pushlightuserdata(L, obj->collided_with);
else
lua_pushnumber(L,0);
}
if (!strcmp(str,"type"))
lua_pushnumber(L,obj->type);
Lua sends the string to a C func; the c func pushes it on the stack.
Ok I could optimize to avoid the string comparison; but it's rather primitive and messy.
Again, I assume my lack of Lua knowledge is the main issue.
Looked at SWIG stuff; went EH!; and decided that was more trouble than it was worth.
Ho-hum!, crude method works- just feels rather cack when I spend lots of my time holding onto 60fps to have some crappy scripting to C interface be so poor.
Spank me if I am talking rubbish; I need it!
Cheers
Lua has a specific value for NULL (nil or none or something?). Why not just use that instead?
Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
I think os c is right you can't compare userdata against null , nil or whatever
OK!,
Finally got what I want.
I had lots of issues (apart from it being a horrible cludge!).
One problem was simply strcmp potentially loads of strings everytime my c service function is called from Lua.
Here's my 'fix'; not for faint of heart or mind :-)
//define some 'define's' for lua and also a type (float,int whatever)
#define PARAM_FLOAT 0
#define PARAM_INT 1
#define PARAM_PTR 2
#define LUA_body_p_x 0
#define LUA_body_p_x_str "LUA_body_p_x"
#define LUA_collided_with 1
#define LUA_collided_with_str "LUA_collided_with"
#define LUA_body_p_y 2
#define LUA_body_p_y_str "LUA_body_p_y"
#define LUA_type 3
#define LUA_type_str "LUA_type"
....
//Get lua to recognise them
lua_pushstring(L,LUA_body_p_x_str);
lua_pushnumber(L,LUA_body_p_x);
lua_settable (L, LUA_GLOBALSINDEX);
lua_pushstring(L,LUA_collided_with_str);
lua_pushnumber(L,LUA_collided_with);
lua_settable (L, LUA_GLOBALSINDEX);
lua_pushstring(L,LUA_body_p_y_str);
lua_pushnumber(L,LUA_body_p_y);
lua_settable (L, LUA_GLOBALSINDEX);
lua_pushstring(L,LUA_type_str);
lua_pushnumber(L,LUA_type);
lua_settable (L, LUA_GLOBALSINDEX);
struct LOOKUP_STRUCT
{
void *param;
int type;
};
//guts of code (not copy/paste stuff); just so you can see the general idea
int get_obj_struct(lua_State *L)
{
OBJECT_DEF *obj;
int i,type;
float **param_float;
int **param_int;
void **param_ptr;
void *param;
obj=(OBJECT_DEF *)lua_touserdata(L,1);
LOOKUP_STRUCT lookup[10]=
{
&obj->body->p.x,PARAM_FLOAT,
&(*obj->collided_with),PARAM_PTR,
&obj->body->p.y,PARAM_FLOAT,
&obj->type,PARAM_INT,
};
i=lua_tointeger(L,2);
type=(int)lookup[i].type;
if (type==PARAM_FLOAT)
{
param_float=(float **)&lookup[i].param;
lua_pushnumber(L,**param_float);
}
if (type==PARAM_PTR)
{
param_ptr=(void **)&lookup[i].param;
param=*param_ptr;
if (param==NULL)
lua_pushnumber(L,0);
else
lua_pushlightuserdata(L, param);
}
etc. etc.
Then in my lua script I can:
x=get_obj_struct(obj,LUA_body_p_x);
:-)
I anyone knows a nicer, saner method; I would love to hear.
Phew!; now at least getting things in/out Lua won't be too much of a burden.
Cheers
Finally got what I want.
I had lots of issues (apart from it being a horrible cludge!).
One problem was simply strcmp potentially loads of strings everytime my c service function is called from Lua.
Here's my 'fix'; not for faint of heart or mind :-)
//define some 'define's' for lua and also a type (float,int whatever)
#define PARAM_FLOAT 0
#define PARAM_INT 1
#define PARAM_PTR 2
#define LUA_body_p_x 0
#define LUA_body_p_x_str "LUA_body_p_x"
#define LUA_collided_with 1
#define LUA_collided_with_str "LUA_collided_with"
#define LUA_body_p_y 2
#define LUA_body_p_y_str "LUA_body_p_y"
#define LUA_type 3
#define LUA_type_str "LUA_type"
....
//Get lua to recognise them
lua_pushstring(L,LUA_body_p_x_str);
lua_pushnumber(L,LUA_body_p_x);
lua_settable (L, LUA_GLOBALSINDEX);
lua_pushstring(L,LUA_collided_with_str);
lua_pushnumber(L,LUA_collided_with);
lua_settable (L, LUA_GLOBALSINDEX);
lua_pushstring(L,LUA_body_p_y_str);
lua_pushnumber(L,LUA_body_p_y);
lua_settable (L, LUA_GLOBALSINDEX);
lua_pushstring(L,LUA_type_str);
lua_pushnumber(L,LUA_type);
lua_settable (L, LUA_GLOBALSINDEX);
struct LOOKUP_STRUCT
{
void *param;
int type;
};
//guts of code (not copy/paste stuff); just so you can see the general idea
int get_obj_struct(lua_State *L)
{
OBJECT_DEF *obj;
int i,type;
float **param_float;
int **param_int;
void **param_ptr;
void *param;
obj=(OBJECT_DEF *)lua_touserdata(L,1);
LOOKUP_STRUCT lookup[10]=
{
&obj->body->p.x,PARAM_FLOAT,
&(*obj->collided_with),PARAM_PTR,
&obj->body->p.y,PARAM_FLOAT,
&obj->type,PARAM_INT,
};
i=lua_tointeger(L,2);
type=(int)lookup[i].type;
if (type==PARAM_FLOAT)
{
param_float=(float **)&lookup[i].param;
lua_pushnumber(L,**param_float);
}
if (type==PARAM_PTR)
{
param_ptr=(void **)&lookup[i].param;
param=*param_ptr;
if (param==NULL)
lua_pushnumber(L,0);
else
lua_pushlightuserdata(L, param);
}
etc. etc.
Then in my lua script I can:
x=get_obj_struct(obj,LUA_body_p_x);
:-)
I anyone knows a nicer, saner method; I would love to hear.
Phew!; now at least getting things in/out Lua won't be too much of a burden.
Cheers
Alright, I kind of skimmed the majority of this thread after the first couple posts, but I'd suggest looking into AngelScript. It's oriented on C++, but it's not like Obj-C++ is too difficult. (AngelScript's website)
I can write up an Obj-C++ sample using AS on my lunch break, if you'd like. I just recently finished writing an AngelScript implementation for my game engine (which is being built in pure C++ for cross-platform support), but converting it to have an Obj-C interface wouldn't be hard.
For any classes you want to expose to the AngelScript VM, you'd need to either write in C++ or write a wrapper in C++. I can include both if you're interested (I think I'm gonna write this anyway - need to get used to XCode again).
I can write up an Obj-C++ sample using AS on my lunch break, if you'd like. I just recently finished writing an AngelScript implementation for my game engine (which is being built in pure C++ for cross-platform support), but converting it to have an Obj-C interface wouldn't be hard.
For any classes you want to expose to the AngelScript VM, you'd need to either write in C++ or write a wrapper in C++. I can include both if you're interested (I think I'm gonna write this anyway - need to get used to XCode again).
Goodbye.

