Mercurial > pub > dyncall > bindings
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 |