[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: binding issues
- From: Adolf Mathias <dolfi@...>
- Date: Wed, 19 Feb 2003 10:10:20 +0100
Hi folks,
the whole binding issue (tolua vs SWIG etc) went through my mind
recently, and I came up with this atrocity for Lua-5.0 and Linux.
It is of course seriously non-portable, but similar hacks should be
rather easy for other OS and
machines. The C stuff below has to be compiled and registered with
|lua_register(l, "capply", l_capply);
lua_register(l, "dlopen", l_dlopen);
|
Then, one can write stuff like
|dl = dlopen("/lib/libc.so.6")
capply("", dl.srand48)
print("random: ", capply("I", dl.lrand48)) end
dl2 = dlopen("/usr/lib/libm.so")
print("sin:", capply("dD", dl2.sin, 3.14))
|The generation of the spec string could be wrapped up with a simple
parser of C header files and then one could make the whole thing a bit
more typesafe by combining the spec string, a C function and capply into
one closure for each bound C function.
What do you think about it?
Ciao, Dolfi
|/*** feed to gcc -O (and maybe -fomit-frame-pointer) ***/
#include <lua.h>
#include <math.h>
#include <lauxlib.h>
#include "glua.h"
#include <dlfcn.h>
int l_dlgettable(lua_State *l)
{ const char *name, **reg;
void *dl = *(void**)lua_touserdata(l, 1), *value;
int i;
if(!lua_isstring(l, 2))
glua_error("dlgettable expects a string index");
else if(!(value = dlsym(dl, name = lua_tostring(l, -1))))
glua_error("dlsym couldn't access symbol %s", name);
else if(!strcmp(name, "registry"))
{ int cnt = 0;
reg = (const char**)value;
lua_newtable(l);
for(i = 0; name = reg[i]; i++)
if(value = dlsym(dl, name))
{ lua_pushvalue(l, -1); lua_pushstring(l, name);
lua_pushcfunction(l, value); lua_settable(l, -3); }
else
fprintf(stderr, "%s%s", cnt++?", ":"registry symbols
undefined: ", name);
if(cnt) fprintf(stderr, "\n");
}
else if(!strcmp(name, "label"))
{ if(value = dlsym(dl, name))
lua_pushstring(l, *(char**)value);
else
lua_pushnil(l);
}
else
lua_pushlightuserdata(l, value);
return 1;
}
int l_dlclose(lua_State *l)
{ dlclose(lua_touserdata(l, -1));
return 0;
}
int l_dlopen(lua_State *l)
{ void *dl;
const char *name;
if(!lua_isstring(l, -1))
luaL_error(l, "dlopen expects a string argument");
else
{ name = lua_tostring(l, -1);
dl = dlopen(name, RTLD_NOW);
if(!dl)
{ luaL_error("dlopen: %s\n", dlerror()); }
else
{ *(void**)lua_newuserdata(l, 4) = dl;
lua_newtable(l);
lua_pushstring(l, "__gc"); lua_pushcfunction(l, l_dlclose);
lua_settable(l, -3);
lua_pushstring(l, "__index"); lua_pushcfunction(l,
l_dlgettable); lua_settable(l, -3);
lua_setmetatable(l, -2);
fprintf(stderr, "dlopen succeeded\n");
}
}
return 1;
}
#define MAXARG 64
int l_capply(lua_State *l)
{ const char *spec, *specp;
int c = 0, n, top, nword;
register unsigned long __d0, __d1, __d2; /* dummies */
static void *arg[MAXARG], **arge = arg+MAXARG;
void *fn, **argp;
double dres;
long lres;
spec = luaL_checkstring(l, 1);
fn = lua_touserdata(l, 2);
for(specp = spec, argp = arg, n = 3, top = lua_gettop(l); argp<arge
&& n<=top; n++, specp++)
switch(c = *specp)
{ case 'd': *((double*)argp)++ = lua_tonumber(l, n); break;
case 'i': *((signed long *)argp)++ = lua_tonumber(l, n); break;
case 'u': *((unsigned long *)argp)++ = lua_tonumber(l, n); break;
case 's': *((const char**)argp)++ = lua_tostring(l, n); break;
case 'p': *((void**)argp)++ = lua_touserdata(l, n); break;
default : goto LEAVE;
}
LEAVE:
if(argp>arge)
luaL_error(l, "capply: argument buffer size %d exceeded", MAXARG);
if(n>top)
luaL_error(l, "capply: too few args on lua stack for spec
'%s'\n", spec);
nword = argp-arg;
__asm__ __volatile__
("movl %%esp, %%edi\n\t"
"subl %6,%%edi\n\t"
"movl %%edi,%%esp\n\t"
"cld\n\t"
"rep\n\t"
"movsl\n\t"
"call *%7\n\t"
"movl %%edi,%%esp\n\t"
"movl %%eax, %3\n\t"
: "=&c" (__d0), "=&S" (__d1), "=&D" (__d2), "=m" (lres)
: "0" (nword), "1" (arg), "r" (nword<<2), "a" (fn)
: "cc");
switch(*specp)
{ case 'D':
__asm__ __volatile__ ("fstpl %0": "=m" (dres));
lua_pushnumber(l, dres); return 1;
case 'I':
lua_pushnumber(l, lres); return 1;
case 'U':
lua_pushnumber(l, (unsigned long)lres); return 1;
case 'S':
lua_pushstring(l, (unsigned char *)lres); return 1;
default:
return 0;
}
}
|