diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib_ffi.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index f4097041..e7d31fe7 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
@@ -206,31 +206,34 @@ LJLIB_CF(ffi_meta___concat) LJLIB_REC(cdata_arith MM_concat) | |||
206 | return ffi_arith(L); | 206 | return ffi_arith(L); |
207 | } | 207 | } |
208 | 208 | ||
209 | /* Handle ctype __call metamethod. */ | ||
210 | static int ffi_call_meta(lua_State *L, CTypeID id) | ||
211 | { | ||
212 | CTState *cts = ctype_cts(L); | ||
213 | CType *ct = ctype_raw(cts, id); | ||
214 | cTValue *tv; | ||
215 | if (ctype_isptr(ct->info)) id = ctype_cid(ct->info); | ||
216 | tv = lj_ctype_meta(cts, id, MM_call); | ||
217 | if (!tv) | ||
218 | lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL))); | ||
219 | return lj_meta_tailcall(L, tv); | ||
220 | } | ||
221 | |||
222 | /* Forward declaration. */ | 209 | /* Forward declaration. */ |
223 | static int lj_cf_ffi_new(lua_State *L); | 210 | static int lj_cf_ffi_new(lua_State *L); |
224 | 211 | ||
225 | LJLIB_CF(ffi_meta___call) LJLIB_REC(cdata_call) | 212 | LJLIB_CF(ffi_meta___call) LJLIB_REC(cdata_call) |
226 | { | 213 | { |
214 | CTState *cts = ctype_cts(L); | ||
227 | GCcdata *cd = ffi_checkcdata(L, 1); | 215 | GCcdata *cd = ffi_checkcdata(L, 1); |
228 | int ret; | 216 | CTypeID id = cd->typeid; |
229 | if (cd->typeid == CTID_CTYPEID) | 217 | CType *ct; |
230 | return lj_cf_ffi_new(L); | 218 | cTValue *tv; |
231 | if ((ret = lj_ccall_func(L, cd)) < 0) | 219 | MMS mm = MM_call; |
232 | return ffi_call_meta(L, cd->typeid); | 220 | if (cd->typeid == CTID_CTYPEID) { |
233 | return ret; | 221 | id = *(CTypeID *)cdataptr(cd); |
222 | mm = MM_new; | ||
223 | } else { | ||
224 | int ret = lj_ccall_func(L, cd); | ||
225 | if (ret >= 0) | ||
226 | return ret; | ||
227 | } | ||
228 | /* Handle ctype __call/__new metamethod. */ | ||
229 | ct = ctype_raw(cts, id); | ||
230 | if (ctype_isptr(ct->info)) id = ctype_cid(ct->info); | ||
231 | tv = lj_ctype_meta(cts, id, mm); | ||
232 | if (tv) | ||
233 | return lj_meta_tailcall(L, tv); | ||
234 | else if (mm == MM_call) | ||
235 | lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL))); | ||
236 | return lj_cf_ffi_new(L); | ||
234 | } | 237 | } |
235 | 238 | ||
236 | LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add) | 239 | LJLIB_CF(ffi_meta___add) LJLIB_REC(cdata_arith MM_add) |