[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cinvoke-svn] r38 - trunk/cinvoke/bindings/lua
From: |
will |
Subject: |
[cinvoke-svn] r38 - trunk/cinvoke/bindings/lua |
Date: |
23 Jun 2006 00:39:49 -0400 |
Author: will
Date: 2006-06-23 00:39:48 -0400 (Fri, 23 Jun 2006)
New Revision: 38
Modified:
trunk/cinvoke/bindings/lua/cinvoke_lua.c
Log:
very functional lua binding
Modified: trunk/cinvoke/bindings/lua/cinvoke_lua.c
===================================================================
--- trunk/cinvoke/bindings/lua/cinvoke_lua.c 2006-06-21 05:34:33 UTC (rev 37)
+++ trunk/cinvoke/bindings/lua/cinvoke_lua.c 2006-06-23 04:39:48 UTC (rev 38)
@@ -4,96 +4,6 @@
#include <stdio.h>
#include <string.h>
-void declbasic(lua_State *l, const char *g,
- cinv_type_t id, char charid, int size) {
- lua_newtable(l);
- lua_pushstring(l, "basic");
- lua_setfield(l, -2, "family");
- lua_pushinteger(l, (lua_Integer)id);
- lua_setfield(l, -2, "id");
- lua_pushinteger(l, (lua_Integer)charid);
- lua_setfield(l, -2, "charid");
- lua_pushinteger(l, (lua_Integer)size);
- lua_setfield(l, -2, "size");
- lua_setglobal(l, g);
-}
-
-void declfunc(lua_State *l, const char *name, lua_CFunction func) {
- lua_pushcfunction(l, func);
- lua_setfield(l, -2, name);
-}
-
-int _cinv_chararray_to_string(lua_State *l) {
- size_t len, i = 0;
- if (lua_gettop(l) != 0) {
- lua_pushstring(l, "usage: cinv.chararray_to_string(carray)");
- lua_error(l);
- }
- len = lua_objlen(l, 1);
-
- if (len == 0) {
- lua_pushlstring(l, "", len);
- } else {
- char *ret = malloc(len + 1);
- if (!ret) {
- lua_pushstring(l, "out of memory");
- lua_error(l);
- }
- lua_pushnil(l);
- while (lua_next(l, 1) != 0) {
- if (i >= len) break;
-
- ret[i] = (char)lua_tointeger(l, -1);
-
- lua_pop(l, 1);
- i++;
- }
-
- ret[len] = '\0';
- lua_pushlstring(l, ret, len);
- free(ret);
- }
-
- return 1;
-}
-int _cinv_array(lua_State *l) {
- if (lua_gettop(l) != 1) {
- lua_pushstring(l, "usage: cinv.array(arrtype)");
- lua_error(l);
- }
-
- lua_getfield(l, 1, "array");
- if (!lua_isnil(l, -1)) {
- lua_pushstring(l, "arrays of arrays not supported");
- lua_error(l);
- }
- lua_pop(l, 1);
- lua_getfield(l, 1, "family");
- if (!strcmp(lua_tostring(l, -1), "void")) {
- lua_pushstring(l, "void is not a type");
- lua_error(l);
- }
- if (!strcmp(lua_tostring(l, -1), "struct")) {
- lua_pushstring(l, "arrays of structs not supported");
- lua_error(l);
- }
- lua_pop(l, 1);
-
- lua_newtable(l);
- lua_pushnil(l);
- while (lua_next(l, 1) != 0) {
- lua_pushvalue(l, -2);
- lua_pushvalue(l, -2);
- lua_settable(l, -5);
- lua_pop(l, 1);
- }
-
- lua_pushstring(l, "yes");
- lua_setfield(l, -2, "array");
-
- return 1;
-}
-
struct LibStruct {
CInvContext *ctx;
CInvLibrary *lib;
@@ -174,11 +84,42 @@
return 0;
}
+int isvoid(lua_State *l, int index) {
+ int ret;
+ lua_getfield(l, index, "family");
+ ret = !strcmp("void", lua_tostring(l, -1));
+ lua_pop(l, 1);
+ return ret;
+}
+int isarray(lua_State *l, int index) {
+ int ret = 0;
+ lua_getfield(l, index, "array");
+ if (!lua_isnil(l, -1))
+ ret = 1;
+ lua_pop(l, 1);
+ return ret;
+}
+int isstruct(lua_State *l, int index) {
+ int ret;
+ lua_getfield(l, index, "family");
+ ret = !strcmp("struct", lua_tostring(l, -1));
+ lua_pop(l, 1);
+ return ret;
+}
+int isstring(lua_State *l, int index) {
+ int ret;
+ lua_getfield(l, index, "family");
+ ret = !strcmp("string", lua_tostring(l, -1));
+ lua_pop(l, 1);
+ return ret;
+}
+
int _cstructure_new(lua_State *l) {
struct StrStruct *ptr;
CInvContext *ctx;
CInvStructure *st;
int numargs, i;
+ int size;
ctx = cinv_context_create();
if (ctx == NULL) {
@@ -202,19 +143,18 @@
for (i = 1; i <= numargs; i += 2) {
const char *family;
- int isarray = 0;
- lua_getfield(l, i, "array");
- if (!lua_isnil(l, -1))
- isarray = 1;
- lua_pop(l, 1);
+ if (isarray(l, i)) {
+ lua_pushstring(l, "array structure members not
supported");
+ lua_error(l);
+ }
lua_getfield(l, i, "family");
family = lua_tostring(l, -1);
if (!strcmp(family, "void")) {
lua_pushstring(l, "void is not a type");
goto error;
- } else if (isarray || !strcmp(family, "string")) {
+ } else if (!strcmp(family, "string")) {
if (!cinv_structure_addmember_value(ctx, st,
lua_tostring(l, i + 1), CINV_T_PTR)) {
lua_pushstring(l,
cinv_context_get_errormsg(ctx));
@@ -264,6 +204,13 @@
}
lua_setfield(l, -2, "members");
+ if (!cinv_structure_get_size(ctx, st, &size)) {
+ lua_pushstring(l, cinv_context_get_errormsg(ctx));
+ goto error;
+ }
+ lua_pushinteger(l, size);
+ lua_setfield(l, -2, "size");
+
ptr = lua_newuserdata(l, sizeof(struct StrStruct));
ptr->ctx = ctx;
ptr->st = st;
@@ -316,12 +263,21 @@
int numparms = lua_gettop(l) - startarg - 1;
const char *family;
- lua_getfield(l, startarg, "array");
- if (!lua_isnil(l, -1)) {
+ if (lua_isnil(l, startarg)) {
+ lua_pushstring(l, "got nil value instead of type");
+ lua_error(l);
+ }
+ lua_getfield(l, startarg, "family");
+ if (lua_isnil(l, -1)) {
+ lua_pushstring(l, "invalid type");
+ lua_error(l);
+ }
+ lua_pop(l, 1);
+ if (isarray(l, startarg)) {
lua_pushstring(l, "returning arrays not supported");
lua_error(l);
}
- lua_pop(l, 1);
+
lua_getfield(l, startarg, "family");
family = lua_tostring(l, -1);
if (!strcmp("void", family))
@@ -339,8 +295,16 @@
lua_pushstring(l, "out of memory");
lua_error(l);
}
- for (i = startarg + 2; i <= numparms; i++) {
+ for (i = startarg + 2; i < (numparms + startarg + 2); i++) {
+ if (lua_isnil(l, i)) {
+ lua_pushstring(l, "got nil value instead of type");
+ lua_error(l);
+ }
lua_getfield(l, i, "family");
+ if (lua_isnil(l, -1)) {
+ lua_pushstring(l, "invalid type");
+ lua_error(l);
+ }
family = lua_tostring(l, -1);
if (!strcmp("void", family)) {
// only put up with void if it is the first and only
parameter
@@ -392,53 +356,231 @@
return 0;
}
-int isvoid(lua_State *l, int tblindex) {
+int get_arrelement_size(lua_State *l, int type) {
int ret;
- lua_getfield(l, tblindex, "family");
- ret = !strcmp("void", lua_tostring(l, -1));
+ lua_getfield(l, type, "size");
+ ret = lua_tointeger(l, -1);
lua_pop(l, 1);
return ret;
}
+void *get_ptr_val(lua_State *l, int index) {
+ void *ret;
+ const char *pstr;
+ if (lua_isnil(l, index))
+ return 0;
+ pstr = lua_tostring(l, index);
+ if (strlen(pstr) == 0) return 0;
+ if (strlen(pstr) == 1 ||
+ strncmp("0x", pstr, 2)) {
+ char *endptr;
+ ret = (void *)strtol(pstr, &endptr, 10);
+ if (*endptr != '\0') {
+ lua_pushstring(l, "invalid pointer value");
+ lua_error(l);
+ }
+ } else {
+ if (sscanf(pstr, "%p", &ret) == 0) {
+ lua_pushstring(l, "invalid pointer value");
+ lua_error(l);
+ }
+ }
+ return ret;
+}
+
void *allocreturn(lua_State *l, int typeindex) {
- int sz, isarray = 0;
+ int sz = get_arrelement_size(l, typeindex);
void *ret;
- lua_getfield(l, typeindex, "array");
- if (!lua_isnil(l, -1))
- isarray = 1;
- lua_pop(l, 1);
- lua_getfield(l, typeindex, "family");
- if (isarray || !strcmp(lua_tostring(l, -1), "string")) {
- sz = sizeof(void*);
- } else { // basic
- lua_getfield(l, typeindex, "size");
- sz = lua_tointeger(l, -1);
- lua_pop(l, 1);
+ ret = malloc(sz);
+ if (!ret) {
+ lua_pushstring(l, "out of memory");
+ lua_error(l);
}
+ return ret;
+}
+void marshal_struct(lua_State *l, void *ret, int typeindex, int argindex) {
+ // XXX
+}
+void marshal_string(lua_State *l, void *ret, int argindex) {
+ if (lua_isnil(l, argindex))
+ *(const char **)ret = NULL;
+ else
+ *(const char **)ret = lua_tostring(l, argindex);
+}
+void marshal_basic(lua_State *l, void *ret, int typeindex, int argindex) {
+ cinv_type_t id;
+ int isnil;
+
+ lua_getfield(l, typeindex, "id");
+ id = (cinv_type_t)lua_tointeger(l, -1);
lua_pop(l, 1);
- ret = malloc(sz);
+ isnil = lua_isnil(l, argindex);
+ if (isnil && id != CINV_T_PTR) {
+ lua_pushstring(l, "cannot convert nil to a number");
+ lua_error(l);
+ }
+
+ switch (id) {
+ case CINV_T_CHAR:
+ *(char*)ret = lua_tostring(l, argindex)[0];
+ break;
+ case CINV_T_SHORT:
+ *(short*)ret = (short)lua_tointeger(l, argindex);
+ break;
+ case CINV_T_INT:
+ *(int*)ret = (int)lua_tointeger(l, argindex);
+ break;
+ case CINV_T_LONG:
+ *(long*)ret = (long)lua_tonumber(l, argindex);
+ break;
+ case CINV_T_EXTRALONG:
+ *(long long*)ret = (long long)lua_tonumber(l, argindex);
+ break;
+ case CINV_T_FLOAT:
+ *(float*)ret = (float)lua_tonumber(l, argindex);
+ break;
+ case CINV_T_DOUBLE:
+ *(double*)ret = (double)lua_tonumber(l, argindex);
+ break;
+ case CINV_T_PTR:
+ *(void**)ret = get_ptr_val(l, argindex);
+ break;
+ default:
+ lua_pushstring(l, "unknown type");
+ lua_error(l);
+ }
+}
+void *marshal_param(lua_State *l, int typeindex, int argindex) {
+ void *ret = NULL;
+ if (isarray(l, typeindex)) {
+ char **ptr = malloc(sizeof(char *));
+ if (ptr) {
+ int arrlen = lua_objlen(l, argindex);
+ int elsize = get_arrelement_size(l, typeindex);
+ *ptr = malloc(arrlen * elsize);
+ if (*ptr) {
+ int i;
+ char *tmp = *ptr;
+
+ for (i = 1; i <= arrlen; i++) {
+ lua_pushinteger(l, i);
+ lua_gettable(l, argindex);
+
+ if (lua_isnil(l, -1)) break;
+
+ if (isstruct(l, typeindex))
+ marshal_struct(l, tmp,
typeindex, lua_gettop(l));
+ if (isstring(l, typeindex))
+ marshal_string(l, tmp,
lua_gettop(l));
+ else
+ marshal_basic(l, tmp,
typeindex, lua_gettop(l));
+
+ lua_pop(l, 1);
+
+ tmp += elsize;
+ }
+
+ ret = ptr;
+ } else
+ free(ptr);
+ }
+ } else {
+ ret = malloc(get_arrelement_size(l, typeindex));
+ if (ret) {
+ if (isstring(l, typeindex))
+ marshal_string(l, ret, argindex);
+ else
+ marshal_basic(l, ret, typeindex, argindex);
+ }
+ }
if (!ret) {
lua_pushstring(l, "out of memory");
lua_error(l);
}
return ret;
}
-void *marshal(lua_State *l, int typeindex, int argindex) {
- // XXX
- return NULL;
+void free_param(lua_State *l, int typeindex, void *value) {
+ if (isarray(l, typeindex)) {
+ char **arr = value;
+ free(*arr);
+ free(arr);
+ } else
+ free(value);
}
void unmarshal_retval(lua_State *l, int typeindex, void *value) {
- // XXX can be basic, string, or struct
+ // can be basic or string
// push completed value on stack
+ int famindex;
+ lua_getfield(l, typeindex, "family");
+ famindex = lua_gettop(l);
+ if (!strcmp("basic", lua_tostring(l, famindex))) {
+ char ptrbuf[16];
+ char strbuf[2];
+ int idindex;
+ lua_getfield(l, typeindex, "id");
+ idindex = lua_gettop(l);
+ switch ((cinv_type_t)lua_tointeger(l, idindex)) {
+ case CINV_T_CHAR:
+ strbuf[0] = *(char *)value;
+ strbuf[1] = '\0';
+ lua_pushlstring(l, strbuf, 1);
+ break;
+ case CINV_T_SHORT:
+ lua_pushinteger(l, *(short *)value);
+ break;
+ case CINV_T_INT:
+ lua_pushinteger(l, *(int *)value);
+ break;
+ case CINV_T_LONG:
+ lua_pushnumber(l, *(long *)value);
+ break;
+ case CINV_T_EXTRALONG:
+ lua_pushnumber(l, *(long long *)value);
+ break;
+ case CINV_T_FLOAT:
+ lua_pushnumber(l, *(float *)value);
+ break;
+ case CINV_T_DOUBLE:
+ lua_pushnumber(l, *(float *)value);
+ break;
+ case CINV_T_PTR:
+ sprintf(ptrbuf, "%p", *(void **)value);
+ lua_pushstring(l, ptrbuf);
+ break;
+ default:
+ lua_pushstring(l, "unknown type");
+ lua_error(l);
+ break;
+ }
+ lua_remove(l, idindex);
+ } else
+ lua_pushstring(l, *(char **)value);
+ lua_remove(l, famindex);
}
+void unmarshal_struct(lua_State *l, int typeindex, void *instance) {
+ lua_newtable(l);
+
+ // XXX set values
+}
void unmarshal_array(lua_State *l, int typeindex, void *value, int outindex) {
- // XXX
+ char *cptr = (char *)value;
+ int arrlen = lua_objlen(l, outindex), i;
+ int elsize = get_arrelement_size(l, typeindex);
+
+ for (i = 1; i <= arrlen; i++) {
+ lua_pushinteger(l, i);
+
+ if (isstruct(l, typeindex))
+ unmarshal_struct(l, typeindex, cptr);
+ else
+ unmarshal_retval(l, typeindex, cptr);
+
+ lua_settable(l, outindex);
+ cptr += elsize;
+ }
}
-void unmarshal_struct(lua_State *l, int typeindex, void *value, int outindex) {
- // XXX
-}
int _function_call(lua_State *l) {
struct FunStruct *fs;
@@ -469,7 +611,7 @@
index = lua_gettop(l);
- parameters[i] = marshal(l, index, i + 2);
+ parameters[i] = marshal_param(l, index, i + 2);
lua_remove(l, index);
}
@@ -490,11 +632,9 @@
if (!lua_isnil(l, -1))
unmarshal_array(l, index, parameters[i], i + 2);
lua_pop(l, 1);
- lua_getfield(l, index, "family");
- if (!strcmp("struct", lua_tostring(l, -1)))
- unmarshal_struct(l, index, parameters[i], i + 2);
- lua_pop(l, 1);
+ free_param(l, index, parameters[i]);
+
lua_remove(l, index);
}
lua_remove(l, pindex);
@@ -507,8 +647,6 @@
lua_remove(l, index);
}
- for (i = 0; i < numargs; i++)
- free(parameters[i]);
free(parameters);
free(returnval);
@@ -576,8 +714,194 @@
return 1;
}
+void declbasic(lua_State *l, const char *g,
+ cinv_type_t id, char charid, int size) {
+ lua_newtable(l);
+ lua_pushstring(l, "basic");
+ lua_setfield(l, -2, "family");
+ lua_pushinteger(l, (lua_Integer)id);
+ lua_setfield(l, -2, "id");
+ lua_pushinteger(l, (lua_Integer)charid);
+ lua_setfield(l, -2, "charid");
+ lua_pushinteger(l, (lua_Integer)size);
+ lua_setfield(l, -2, "size");
+ lua_setglobal(l, g);
+}
+
+void declfunc(lua_State *l, const char *name, lua_CFunction func) {
+ lua_pushcfunction(l, func);
+ lua_setfield(l, -2, name);
+}
+
+int _cinv_chararray_to_string(lua_State *l) {
+ size_t len, i = 0;
+ if (lua_gettop(l) != 1) {
+ lua_pushstring(l, "usage: cinv.chararray_to_string(carray)");
+ lua_error(l);
+ }
+ len = lua_objlen(l, 1);
+
+ if (len == 0) {
+ lua_pushlstring(l, "", len);
+ } else {
+ char *ret = malloc(len + 1);
+ if (!ret) {
+ lua_pushstring(l, "out of memory");
+ lua_error(l);
+ }
+ lua_pushnil(l);
+ while (lua_next(l, 1) != 0) {
+ if (i >= len) break;
+
+ ret[i] = (char)lua_tointeger(l, -1);
+
+ lua_pop(l, 1);
+ i++;
+ }
+
+ ret[len] = '\0';
+ lua_pushlstring(l, ret, len);
+ free(ret);
+ }
+
+ return 1;
+}
+
+int _cinv_ptr_to_string(lua_State *l) {
+ char *ptr;
+ int len = -1;
+ if (lua_gettop(l) != 1 || lua_gettop(l) != 2) {
+ lua_pushstring(l, "usage: cinv.ptr_to_string(cptr[, len])");
+ lua_error(l);
+ }
+ ptr = get_ptr_val(l, 1);
+ if (!lua_isnil(l, 2)) {
+ len = lua_tointeger(l, 2);
+ if (len < 0) {
+ lua_pushstring(l, "invalid length parameter");
+ lua_error(l);
+ }
+ }
+ if (ptr == NULL)
+ lua_pushnil(l);
+ else if (len != -1)
+ lua_pushlstring(l, ptr, len);
+ else
+ lua_pushstring(l, ptr);
+ return 1;
+}
+
+int _cinv_ptr_to_array(lua_State *l) {
+ int len, i, index;
+ void *value;
+ if (lua_gettop(l) != 3) {
+ lua_pushstring(l, "usage: cinv.ptr_to_array(cptr, arrtype,
len)");
+ lua_error(l);
+ }
+ value = get_ptr_val(l, 1);
+ if (value == NULL)
+ lua_pushnil(l);
+ else {
+ len = lua_tointeger(l, 3);
+ // create table of desired len and call unmarshal_array
+ lua_newtable(l);
+ index = lua_gettop(l);
+ for (i = 1; i <= len; i++) {
+ lua_pushinteger(l, i);
+ lua_pushstring(l, "");
+ lua_settable(l, index);
+ }
+ unmarshal_array(l, 2, value, index);
+ }
+ return 1;
+}
+
+int _cinv_ptr_to_struct(lua_State *l) {
+ void *ptr;
+ if (lua_gettop(l) != 2) {
+ lua_pushstring(l, "usage: cinv.ptr_to_struct(cptr, type)");
+ lua_error(l);
+ }
+ ptr = get_ptr_val(l, 1);
+ if (ptr == NULL)
+ lua_pushnil(l);
+ else
+ unmarshal_struct(l, 2, ptr);
+ return 1;
+}
+
+int _cinv_sizeof(lua_State *l) {
+ if (lua_gettop(l) != 1) {
+ lua_pushstring(l, "usage: cinv.sizeof(type)");
+ lua_error(l);
+ }
+ if (isvoid(l, 1)) {
+ lua_pushstring(l, "void is not a type");
+ lua_error(l);
+ }
+ if (isarray(l, 1)) {
+ lua_pushstring(l, "cannot get size of array types");
+ lua_error(l);
+ }
+
+ lua_pushinteger(l, get_arrelement_size(l, 1));
+ return 1;
+}
+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);
+ }
+
+ num = lua_tointeger(l, 2);
+ ptr = get_ptr_val(l, 1);
+
+ ptr += num;
+ sprintf(ret, "%p", ptr);
+ lua_pushstring(l, ret);
+
+ return 1;
+}
+
+int _cinv_array(lua_State *l) {
+ if (lua_gettop(l) != 1) {
+ lua_pushstring(l, "usage: cinv.array(arrtype)");
+ lua_error(l);
+ }
+
+ lua_getfield(l, 1, "array");
+ if (!lua_isnil(l, -1)) {
+ lua_pushstring(l, "arrays of arrays not supported");
+ lua_error(l);
+ }
+ lua_pop(l, 1);
+ lua_getfield(l, 1, "family");
+ if (!strcmp(lua_tostring(l, -1), "void")) {
+ lua_pushstring(l, "void is not a type");
+ lua_error(l);
+ }
+ lua_pop(l, 1);
+
+ lua_newtable(l);
+ lua_pushnil(l);
+ while (lua_next(l, 1) != 0) {
+ lua_pushvalue(l, -2);
+ lua_pushvalue(l, -2);
+ lua_settable(l, -5);
+ lua_pop(l, 1);
+ }
+
+ lua_pushstring(l, "yes");
+ lua_setfield(l, -2, "array");
+
+ return 1;
+}
+
+
int luaopen_cinvoke_lua(lua_State *l) {
- // XXX might want to put these in the cinv class to prevent typo errors
declbasic(l, "Cchar", CINV_T_CHAR, 'c', 1);
declbasic(l, "Cshort", CINV_T_SHORT, 's', sizeof(short));
declbasic(l, "Cint", CINV_T_INT, 'i', sizeof(int));
@@ -593,6 +917,8 @@
lua_newtable(l);
lua_pushstring(l, "string");
lua_setfield(l, -2, "family");
+ lua_pushinteger(l, sizeof(char*));
+ lua_setfield(l, -2, "size");
lua_setglobal(l, "Cstring");
lua_newtable(l);
@@ -603,6 +929,11 @@
lua_newtable(l);
declfunc(l, "array", _cinv_array);
declfunc(l, "chararray_to_string", _cinv_chararray_to_string);
+ 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, "sizeof", _cinv_sizeof);
+ declfunc(l, "ptr_incr", _cinv_ptr_incr);
lua_setglobal(l, "cinv");
lua_newtable(l);
@@ -621,4 +952,3 @@
return 0;
}
-
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [cinvoke-svn] r38 - trunk/cinvoke/bindings/lua,
will <=