cinvoke-svn
[Top][All Lists]
Advanced

[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");





reply via email to

[Prev in Thread] Current Thread [Next in Thread]