0
|
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
|