[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cinvoke-svn] r44 - in trunk/cinvoke: . bindings/lua
From: |
will |
Subject: |
[cinvoke-svn] r44 - in trunk/cinvoke: . bindings/lua |
Date: |
25 Jun 2006 12:15:18 -0400 |
Author: will
Date: 2006-06-25 12:15:18 -0400 (Sun, 25 Jun 2006)
New Revision: 44
Modified:
trunk/cinvoke/TODO
trunk/cinvoke/bindings/lua/cinvoke_lua.c
Log:
lua binding "code complete"
Modified: trunk/cinvoke/TODO
===================================================================
--- trunk/cinvoke/TODO 2006-06-25 05:03:57 UTC (rev 43)
+++ trunk/cinvoke/TODO 2006-06-25 16:15:18 UTC (rev 44)
@@ -1,4 +1,3 @@
-lua callbacks, tied variables
amd64 port
ppc port
java binding
Modified: trunk/cinvoke/bindings/lua/cinvoke_lua.c
===================================================================
--- trunk/cinvoke/bindings/lua/cinvoke_lua.c 2006-06-25 05:03:57 UTC (rev 43)
+++ trunk/cinvoke/bindings/lua/cinvoke_lua.c 2006-06-25 16:15:18 UTC (rev 44)
@@ -5,14 +5,8 @@
#include <string.h>
#include <time.h>
-// XXX add callbacks to type system
-
-struct LibStruct {
- CInvContext *ctx;
- CInvLibrary *lib;
- cinv_callconv_t cc;
-};
-
+// stack reading functions, we define our own so we can specify
+// the exact semantics/errors we want
void expected(lua_State *l, const char *exp, int index) {
char err[256];
snprintf(err, sizeof(err), "expected %s, got %s",
@@ -34,6 +28,11 @@
expected(l, "userdata", index);
return lua_touserdata(l, index);
}
+void *tolightuserdata(lua_State *l, int index) {
+ if (lua_type(l, index) != LUA_TLIGHTUSERDATA)
+ expected(l, "lightuserdata", index);
+ return lua_touserdata(l, index);
+}
lua_Integer tointeger(lua_State *l, int index) {
if (lua_type(l, index) != LUA_TNUMBER)
expected(l, "integer", index);
@@ -45,6 +44,12 @@
return lua_tonumber(l, index);
}
+struct LibStruct {
+ CInvContext *ctx;
+ CInvLibrary *lib;
+ cinv_callconv_t cc;
+};
+
int _clibrary_new(lua_State *l) {
CInvContext *ctx;
CInvLibrary *lib;
@@ -83,28 +88,28 @@
lua_error(l);
}
- lua_newtable(l);
+ lua_newtable(l); // push return value
- lua_newtable(l);
+ lua_newtable(l); // metatable for return value
lua_getglobal(l, "clibrary");
lua_setfield(l, -2, "__index");
lua_setmetatable(l, -2);
- st = lua_newuserdata(l, sizeof(struct LibStruct)); // return value
+ st = lua_newuserdata(l, sizeof(struct LibStruct));
st->ctx = ctx;
st->lib = lib;
st->cc = cc;
- lua_newtable(l);
+ lua_newtable(l); // metatable for userdata
lua_getglobal(l, "clibrary");
lua_getfield(l, -1, "dispose");
lua_setfield(l, -3, "__gc");
- lua_pop(l, 1);
+ lua_pop(l, 1); // pop the clibrary global
lua_setmetatable(l, -2);
- lua_setfield(l, -2, "ud");
+ lua_setfield(l, -2, "ud"); // save userdata in return value
- lua_newtable(l);
+ lua_newtable(l); // table for holding tied variables
lua_setfield(l, -2, "ties");
return 1;
@@ -117,11 +122,14 @@
lua_error(l);
}
+ // this function can be called from the __gc metatable
+ // or by the user with dispose, handle both cases
if (lua_type(l, 1) == LUA_TUSERDATA)
st = touserdata(l, 1);
else {
lua_getfield(l, 1, "ud");
st = touserdata(l, -1);
+ lua_pop(l, 1);
}
if (st->ctx) {
if (st->lib) {
@@ -134,6 +142,7 @@
return 0;
}
+// some functions dealing with the type system
int isvoid(lua_State *l, int index) {
int ret;
lua_getfield(l, index, "family");
@@ -170,6 +179,13 @@
lua_pop(l, 1);
return ret;
}
+int iscallback(lua_State *l, int index) {
+ int ret;
+ lua_getfield(l, index, "family");
+ ret = !strcmp("callback", tostring(l, -1));
+ lua_pop(l, 1);
+ return ret;
+}
// dont need explicit dispose methods for structures, callbacks or functions
struct StrStruct {
@@ -229,6 +245,9 @@
if (!strcmp(family, "void")) {
lua_pushstring(l, "void is not a type");
goto error;
+ } else if (!strcmp(family, "callback")) {
+ lua_pushstring(l, "callbacks cannot be struct members");
+ goto error;
} else if (!strcmp(family, "string")) {
if (!cinv_structure_addmember_value(ctx, st,
tostring(l, i + 1), CINV_T_PTR)) {
@@ -267,11 +286,12 @@
goto error;
}
- lua_newtable(l);
+ lua_newtable(l); // return value
+ // we dont need a metatable for this because there are no methods
lua_pushstring(l, "struct");
lua_setfield(l, -2, "family");
- lua_newtable(l);
+ lua_newtable(l); // copy arguments to members table
for (i = 1; i <= numargs; i += 2) {
lua_pushvalue(l, i + 1);
lua_pushvalue(l, i);
@@ -289,12 +309,12 @@
ptr = lua_newuserdata(l, sizeof(struct StrStruct));
ptr->ctx = ctx;
ptr->st = st;
- lua_newtable(l);
+ lua_newtable(l); // metatable for userdata
lua_pushcfunction(l, _cstructure_gc);
lua_setfield(l, -2, "__gc");
lua_setmetatable(l, -2);
- lua_setfield(l, -2, "ud");
+ lua_setfield(l, -2, "ud"); // set userdata to field
return 1;
@@ -302,9 +322,10 @@
cinv_structure_delete(ctx, st);
cinv_context_delete(ctx);
lua_error(l);
- return 0;
+ return 0; // never executed
}
+// helper for parsefunction
char getcode(lua_State *l, const char *family, int tblindex, int callback) {
if (isarray(l, tblindex)) {
if (callback) {
@@ -320,6 +341,12 @@
return (char)-1;
} else if (!strcmp(family, "string")) {
return 'p';
+ } else if (!strcmp(family, "callback")) {
+ if (callback) {
+ lua_pushstring(l, "callbacks cannot accept callbacks as
arguments");
+ return (char)-1;
+ }
+ return 'p';
} else if (!strcmp(family, "basic")) {
lua_getfield(l, tblindex, "charid");
lua_Integer charid = tointeger(l, -1);
@@ -354,6 +381,10 @@
lua_pushstring(l, "returning arrays not supported");
lua_error(l);
}
+ if (iscallback(l, startarg)) {
+ lua_pushstring(l, "returning callbacks not supported");
+ lua_error(l);
+ }
if (callback && isstring(l, startarg)) {
lua_pushstring(l, "callbacks cannot return strings");
lua_error(l);
@@ -424,6 +455,11 @@
lua_pop(l, 1);
return ret;
}
+void push_ptr_val(lua_State *l, void *ptr) {
+ char buf[16];
+ sprintf(buf, "%p", ptr);
+ lua_pushstring(l, buf);
+}
void *get_ptr_val(lua_State *l, int index) {
void *ret;
const char *pstr;
@@ -460,6 +496,15 @@
}
return ret;
}
+void marshal_callback(lua_State *l, void *ret, int argindex) {
+ if (lua_isnil(l, argindex))
+ *(void **)ret = NULL;
+ else {
+ lua_getfield(l, argindex, "ep");
+ *(void **)ret = tolightuserdata(l, -1);
+ lua_pop(l, 1);
+ }
+}
void marshal_string(lua_State *l, void *ret, int argindex) {
if (lua_isnil(l, argindex))
*(const char **)ret = NULL;
@@ -576,7 +621,7 @@
if (isstruct(l, typeindex))
marshal_struct(l, tmp,
typeindex, lua_gettop(l));
- if (isstring(l, typeindex))
+ else if (isstring(l, typeindex))
marshal_string(l, tmp,
lua_gettop(l));
else
marshal_basic(l, tmp,
typeindex, lua_gettop(l));
@@ -595,6 +640,8 @@
if (ret) {
if (isstring(l, typeindex))
marshal_string(l, ret, argindex);
+ else if (iscallback(l, typeindex))
+ marshal_callback(l, ret, argindex);
else
marshal_basic(l, ret, typeindex, argindex);
}
@@ -620,7 +667,6 @@
lua_getfield(l, typeindex, "family");
famindex = lua_gettop(l);
if (!strcmp("basic", tostring(l, famindex))) {
- char ptrbuf[16];
char strbuf[2];
int idindex;
lua_getfield(l, typeindex, "id");
@@ -650,8 +696,7 @@
lua_pushnumber(l, *(float *)value);
break;
case CINV_T_PTR:
- sprintf(ptrbuf, "%p", *(void **)value);
- lua_pushstring(l, ptrbuf);
+ push_ptr_val(l, *(void **)value);
break;
default:
lua_pushstring(l, "unknown type");
@@ -870,6 +915,37 @@
return 1;
}
+int _cinv_ptr_to_callback(lua_State *l) {
+ void *p;
+ if (lua_gettop(l) != 1) {
+ lua_pushstring(l, "usage: cinv.ptr_to_callback(cptr)");
+ lua_error(l);
+ }
+
+ p = get_ptr_val(l, 1);
+
+ lua_newtable(l);
+ lua_pushlightuserdata(l, p);
+ lua_setfield(l, -2, "ep");
+
+ return 1;
+}
+int _cinv_callback_to_ptr(lua_State *l) {
+ void *p;
+ if (lua_gettop(l) != 1) {
+ lua_pushstring(l, "usage: cinv.callback_to_ptr(callback)");
+ lua_error(l);
+ }
+
+ lua_getfield(l, 1, "ep");
+ p = tolightuserdata(l, -1);
+ lua_pop(l, 1);
+
+ push_ptr_val(l, p);
+
+ return 1;
+}
+
struct FunStruct {
void *ep;
CInvFunction *func;
@@ -1041,7 +1117,8 @@
lua_error(l);
}
if (!isbasic(l, 2)) {
- lua_pushstring(l, "tied variables cannot be strings or
structs");
+ lua_pushstring(l,
+ "tied variables cannot be strings, structs or
callbacks");
lua_error(l);
}
@@ -1071,19 +1148,55 @@
return 0;
}
int _clibrary_tie_get(lua_State *l) {
+ void *ep;
+
if (lua_gettop(l) != 2) {
lua_pushstring(l, "usage: clibrary:tie_get(name)");
lua_error(l);
}
- // XXX
+
+ lua_getfield(l, 1, "ties");
+ lua_pushvalue(l, 2);
+ lua_gettable(l, -2);
+ if (lua_isnil(l, -1)) {
+ lua_pushstring(l, "a tied variable with that name was not
found");
+ lua_error(l);
+ }
+ lua_getfield(l, -1, "ep");
+ ep = tolightuserdata(l, -1);
+ lua_pop(l, 1);
+
+ lua_getfield(l, -1, "type");
+ unmarshal_retval(l, lua_gettop(l), ep);
+ lua_remove(l, -2);
+ lua_remove(l, -2);
+ lua_remove(l, -2);
+
return 1;
}
int _clibrary_tie_set(lua_State *l) {
+ void *ep;
+
if (lua_gettop(l) != 3) {
lua_pushstring(l, "usage: clibrary:tie_set(name, value)");
lua_error(l);
}
- // XXX
+
+ lua_getfield(l, 1, "ties");
+ lua_pushvalue(l, 2);
+ lua_gettable(l, -2);
+ if (lua_isnil(l, -1)) {
+ lua_pushstring(l, "a tied variable with that name was not
found");
+ lua_error(l);
+ }
+ lua_getfield(l, -1, "ep");
+ ep = tolightuserdata(l, -1);
+ lua_pop(l, 1);
+
+ lua_getfield(l, -1, "type");
+ marshal_basic(l, ep, lua_gettop(l), 3);
+ lua_pop(l, 3);
+
return 0;
}
@@ -1192,6 +1305,14 @@
lua_pushstring(l, "usage: cinv.ptr_to_array(cptr, arrtype,
len)");
lua_error(l);
}
+
+ if (!isstruct(l, 2) &&
+ !isstring(l, 2) &&
+ !isbasic(l, 2)) {
+ lua_pushstring(l, "type is not a valid array type");
+ lua_error(l);
+ }
+
value = get_ptr_val(l, 1);
if (value == NULL)
lua_pushnil(l);
@@ -1244,7 +1365,6 @@
int _cinv_ptr_incr(lua_State *l) {
char *ptr;
int num;
- char ret[16];
if (lua_gettop(l) != 2) {
lua_pushstring(l, "usage: cinv.ptr_incr(cptr, numbytes)");
lua_error(l);
@@ -1254,8 +1374,7 @@
ptr = get_ptr_val(l, 1);
ptr += num;
- sprintf(ret, "%p", ptr);
- lua_pushstring(l, ret);
+ push_ptr_val(l, ptr);
return 1;
}
@@ -1266,18 +1385,18 @@
lua_error(l);
}
- lua_getfield(l, 1, "array");
- if (!lua_isnil(l, -1)) {
+ if (isarray(l, 1)) {
lua_pushstring(l, "arrays of arrays not supported");
lua_error(l);
}
- lua_pop(l, 1);
- lua_getfield(l, 1, "family");
- if (!strcmp(tostring(l, -1), "void")) {
+ if (isvoid(l, 1)) {
lua_pushstring(l, "void is not a type");
lua_error(l);
}
- lua_pop(l, 1);
+ if (iscallback(l, 1)) {
+ lua_pushstring(l, "arrays of callbacks not supported");
+ lua_error(l);
+ }
lua_newtable(l);
lua_pushnil(l);
@@ -1316,6 +1435,13 @@
lua_setglobal(l, "Cstring");
lua_newtable(l);
+ lua_pushstring(l, "callback");
+ lua_setfield(l, -2, "family");
+ lua_pushinteger(l, sizeof(void*));
+ lua_setfield(l, -2, "size");
+ lua_setglobal(l, "Ccallback");
+
+ lua_newtable(l);
lua_pushstring(l, "void");
lua_setfield(l, -2, "family");
lua_setglobal(l, "Cvoid");
@@ -1327,6 +1453,8 @@
declfunc(l, "ptr_to_string", _cinv_ptr_to_string);
declfunc(l, "ptr_to_array", _cinv_ptr_to_array);
declfunc(l, "ptr_to_struct", _cinv_ptr_to_struct);
+ declfunc(l, "ptr_to_callback", _cinv_ptr_to_callback);
+ declfunc(l, "callback_to_ptr", _cinv_callback_to_ptr);
declfunc(l, "sizeof", _cinv_sizeof);
declfunc(l, "ptr_incr", _cinv_ptr_incr);
lua_setglobal(l, "cinv");
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [cinvoke-svn] r44 - in trunk/cinvoke: . bindings/lua,
will <=