comparison lua/luadyncall/src/ldyncall.c @ 0:0cfcc391201f

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:26:28 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:0cfcc391201f
1 #include <stddef.h>
2 #include "lua.h"
3 #include "lauxlib.h"
4 #include "dyncall.h"
5 #include "dyncall_signature.h"
6
7 DCCallVM* g_pCallVM = NULL;
8
9 /**
10 * lua syntax:
11 *
12 * dodyncall( address, signature, ... )
13 *
14 **/
15
16 int lua_dodyncall(lua_State *L)
17 {
18 void* f;
19 const char *callsignature, *s;
20 int top = lua_gettop(L);
21 if (top < 2) return luaL_error(L,"missing arguments #1 'addr' and #2 'signature'");
22
23 if ( lua_iscfunction(L,1) ) f = (void*) lua_tocfunction(L, 1);
24 else if (lua_islightuserdata(L,1) ) f = lua_touserdata(L, 1);
25 else if (lua_isnumber(L,1) ) f = (void*) lua_tointeger(L, 1);
26 else return luaL_argerror(L, 1, "expected a cfunction, userdata or number");
27
28 s = callsignature = luaL_checkstring(L,2);
29
30 /* parse mode */
31
32 // dcMode( g_pCallVM, DC_CALL_C_DEFAULT );
33 dcReset( g_pCallVM );
34
35 char ch;
36 int p = 3;
37 int ptr = 0;
38 while ( (ch = *s++) != DC_SIGCHAR_ENDARG)
39 {
40 if (p > top) return luaL_error(L,"need more arguments (call signature is '%s')", callsignature );
41 if (ptr == 0) {
42 switch(ch)
43 {
44 case '*':
45 ptr++;
46 continue;
47 case DC_SIGCHAR_BOOL:
48 dcArgBool(g_pCallVM, (DCbool) luaL_checkint(L, p) );
49 break;
50 case DC_SIGCHAR_CHAR:
51 case DC_SIGCHAR_UCHAR:
52 dcArgChar(g_pCallVM, (DCchar) luaL_checkint(L, p) );
53 break;
54 case DC_SIGCHAR_SHORT:
55 case DC_SIGCHAR_USHORT:
56 dcArgShort(g_pCallVM, (DCshort) luaL_checkint(L, p) );
57 break;
58 case DC_SIGCHAR_INT:
59 case DC_SIGCHAR_UINT:
60 dcArgInt(g_pCallVM, (DCint) luaL_checknumber(L, p) );
61 break;
62 case DC_SIGCHAR_LONG:
63 case DC_SIGCHAR_ULONG:
64 dcArgLong(g_pCallVM, (DClong) luaL_checknumber(L, p) );
65 break;
66 case DC_SIGCHAR_LONGLONG:
67 case DC_SIGCHAR_ULONGLONG:
68 dcArgLongLong(g_pCallVM, (DClonglong) luaL_checknumber(L, p) );
69 break;
70 case DC_SIGCHAR_FLOAT:
71 dcArgFloat(g_pCallVM, (DCfloat) luaL_checknumber(L, p) );
72 break;
73 case DC_SIGCHAR_DOUBLE:
74 dcArgDouble(g_pCallVM, (DCdouble) luaL_checknumber(L, p) );
75 break;
76 case DC_SIGCHAR_POINTER:
77 dcArgPointer(g_pCallVM, (DCpointer) lua_topointer(L, p) );
78 break;
79 case DC_SIGCHAR_STRING:
80 dcArgPointer(g_pCallVM, (DCpointer) lua_tostring(L, p) );
81 break;
82 default:
83 return luaL_error(L, "invalid typecode '%c' in call signature '%s'", s[0], callsignature);
84 }
85 } else { /* pointer types */
86 switch(ch)
87 {
88 case '*':
89 ptr++;
90 continue;
91 case '<':
92 {
93 const char* begin = s;
94 while ( (ch = *s++) != '>' ) ;
95 const char* end = s;
96 switch( lua_type(L,p) ) {
97 case LUA_TNUMBER:
98 dcArgPointer(g_pCallVM, (DCpointer) (ptrdiff_t) lua_tonumber(L, p) );
99 break;
100 case LUA_TTABLE:
101 lua_pushvalue(L, p); // 1
102 lua_pushliteral(L, "pointer");
103 lua_gettable(L, -2); // 2
104 if ( !lua_isuserdata(L, -1) )
105 luaL_error(L, "pointer type mismatch at argument #%d", p);
106 dcArgPointer(g_pCallVM, (DCpointer) lua_touserdata(L, -1) );
107 lua_pop(L, 2);
108 break;
109 case LUA_TLIGHTUSERDATA:
110 case LUA_TUSERDATA:
111 dcArgPointer(g_pCallVM, (DCpointer) lua_topointer(L, p) );
112 break;
113 default:
114 luaL_error(L, "pointer type mismatch at argument #%d", p);
115 break;
116 }
117 }
118 break;
119 case DC_SIGCHAR_BOOL:
120 case DC_SIGCHAR_CHAR:
121 if ( lua_isstring(L, p) ) {
122 dcArgPointer(g_pCallVM, (DCpointer) lua_tostring(L, p) );
123 break;
124 }
125 case DC_SIGCHAR_UCHAR:
126 case DC_SIGCHAR_SHORT:
127 case DC_SIGCHAR_USHORT:
128 case DC_SIGCHAR_INT:
129 case DC_SIGCHAR_UINT:
130 case DC_SIGCHAR_LONG:
131 case DC_SIGCHAR_ULONG:
132 case DC_SIGCHAR_LONGLONG:
133 case DC_SIGCHAR_ULONGLONG:
134 case DC_SIGCHAR_FLOAT:
135 case DC_SIGCHAR_DOUBLE:
136 case DC_SIGCHAR_POINTER:
137 case DC_SIGCHAR_STRING:
138 case DC_SIGCHAR_VOID:
139 if ( lua_istable(L, p) ) {
140 lua_pushvalue(L, p); // 1
141 lua_pushliteral(L, "pointer");
142 lua_gettable(L, -2); // 2
143 if ( !lua_isuserdata(L, -1) )
144 luaL_error(L, "pointer type mismatch at argument #%d", p);
145 dcArgPointer(g_pCallVM, (DCpointer) lua_touserdata(L, -1) );
146 lua_pop(L, 2);
147 } else
148 dcArgPointer(g_pCallVM, (DCpointer) lua_topointer(L, p) );
149 ptr = 0;
150 break;
151 default:
152 return luaL_error(L, "invalid signature");
153 }
154 }
155
156 ++p;
157 }
158
159 if (top >= p)
160 luaL_error(L,"too many arguments for given signature, expected %d but received %d" , p-3, top-2 );
161
162 switch(*s++)
163 {
164 case DC_SIGCHAR_VOID:
165 dcCallVoid(g_pCallVM, f);
166 return 0;
167 case DC_SIGCHAR_BOOL:
168 lua_pushboolean( L, (int) dcCallBool(g_pCallVM, f) );
169 break;
170 case DC_SIGCHAR_CHAR:
171 case DC_SIGCHAR_UCHAR:
172 lua_pushnumber( L, (lua_Number) ( dcCallChar(g_pCallVM,f) ) );
173 break;
174 case DC_SIGCHAR_SHORT:
175 case DC_SIGCHAR_USHORT:
176 lua_pushnumber( L, (lua_Number)( dcCallShort(g_pCallVM, f) ) );
177 break;
178 case DC_SIGCHAR_INT:
179 case DC_SIGCHAR_UINT:
180 lua_pushnumber( L, (lua_Number)( dcCallInt(g_pCallVM, f) ) );
181 break;
182 case DC_SIGCHAR_LONG:
183 case DC_SIGCHAR_ULONG:
184 lua_pushnumber( L, (lua_Number)( dcCallLong(g_pCallVM, f) ) );
185 break;
186 case DC_SIGCHAR_LONGLONG:
187 case DC_SIGCHAR_ULONGLONG:
188 lua_pushnumber( L, (lua_Number)( dcCallLongLong(g_pCallVM, f) ) );
189 break;
190 case DC_SIGCHAR_FLOAT:
191 lua_pushnumber( L, (lua_Number) dcCallFloat(g_pCallVM, f) );
192 break;
193 case DC_SIGCHAR_DOUBLE:
194 lua_pushnumber( L, (lua_Number) dcCallDouble(g_pCallVM, f) );
195 break;
196 case DC_SIGCHAR_STRING:
197 lua_pushstring( L, (const char*) dcCallPointer(g_pCallVM, f) );
198 break;
199 case DC_SIGCHAR_POINTER:
200 lua_pushlightuserdata( L, dcCallPointer(g_pCallVM, f) );
201 break;
202 case '*':
203 switch(*s++) {
204 case DC_SIGCHAR_UCHAR:
205 case DC_SIGCHAR_CHAR:
206 lua_pushstring( L, dcCallPointer(g_pCallVM, f) );
207 break;
208 default:
209 lua_pushlightuserdata( L, dcCallPointer(g_pCallVM, f) );
210 break;
211 }
212 break;
213 default:
214 return luaL_error(L, "invalid signature");
215 }
216 return 1;
217 }
218
219 int topointer(lua_State* L)
220 {
221 lua_pushlightuserdata(L, (void*) (ptrdiff_t) luaL_checkint(L, 1) );
222 return 1;
223 }
224
225 static const struct luaL_Reg luareg_dyncall[] =
226 {
227 { "dodyncall", lua_dodyncall },
228 { "topointer", topointer },
229 { NULL, NULL }
230 /*
231 { "NewCallVM", lua_dcNewCallVM },
232 { "Mode", lua_dcMode },
233 { "Reset", lua_dcReset },
234 { "ArgBool", lua_dcBool },
235 { "ArgChar", lua_dcChar },
236 { "ArgShort", lua_dcShort },
237 { "ArgInt", lua_dcInt },
238 { "ArgLong", lua_dcLong },
239 { "ArgLongLong", lua_dcLongLong },
240 */
241 };
242
243 void lua_setmetainfo(lua_State *L)
244 {
245 lua_pushliteral(L, "_COPYRIGHT");
246 lua_pushliteral(L, "Copyright (C) 2010 Dyncall Project");
247 lua_settable(L, -3);
248 lua_pushliteral(L, "_DESCRIPTION");
249 lua_pushliteral(L, "lua bindings for dyncall libraries");
250 lua_settable(L, -3);
251 lua_pushliteral(L, "_VERSION");
252 lua_pushliteral(L, "0.1");
253 lua_settable(L, -3);
254 }
255
256 LUA_API int luaopen_ldyncall(lua_State* L)
257 {
258 g_pCallVM = dcNewCallVM(4096);
259 luaL_register(L, "ldyncall", luareg_dyncall);
260 lua_setmetainfo(L);
261 return 1;
262 }
263