3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
25 #include "lj_cparse.h"
28 #include "lj_carith.h"
30 #include "lj_ccallback.h"
32 #include "lj_strfmt.h"
36 /* -- C type checks ------------------------------------------------------- */
38 /* Check first argument for a C type and returns its ID. */
39 static CTypeID
ffi_checkctype(lua_State
*L
, CTState
*cts
, TValue
*param
)
44 lj_err_argtype(L
, 1, "C type");
46 if (tvisstr(o
)) { /* Parse an abstract C type declaration. */
52 cp
.srcname
= strdata(s
);
55 cp
.mode
= CPARSE_MODE_ABSTRACT
|CPARSE_MODE_NOIMPLICIT
;
56 errcode
= lj_cparse(&cp
);
57 if (errcode
) lj_err_throw(L
, errcode
); /* Propagate errors. */
61 if (!tviscdata(o
)) goto err_argtype
;
62 if (param
&& param
< L
->top
) lj_err_arg(L
, 1, LJ_ERR_FFI_NUMPARAM
);
64 return cd
->ctypeid
== CTID_CTYPEID
? *(CTypeID
*)cdataptr(cd
) : cd
->ctypeid
;
68 /* Check argument for C data and return it. */
69 static GCcdata
*ffi_checkcdata(lua_State
*L
, int narg
)
71 TValue
*o
= L
->base
+ narg
-1;
72 if (!(o
< L
->top
&& tviscdata(o
)))
73 lj_err_argt(L
, narg
, LUA_TCDATA
);
77 /* Convert argument to C pointer. */
78 static void *ffi_checkptr(lua_State
*L
, int narg
, CTypeID id
)
80 CTState
*cts
= ctype_cts(L
);
81 TValue
*o
= L
->base
+ narg
-1;
84 lj_err_arg(L
, narg
, LJ_ERR_NOVAL
);
85 lj_cconv_ct_tv(cts
, ctype_get(cts
, id
), (uint8_t *)&p
, o
, CCF_ARG(narg
));
89 /* Convert argument to int32_t. */
90 static int32_t ffi_checkint(lua_State
*L
, int narg
)
92 CTState
*cts
= ctype_cts(L
);
93 TValue
*o
= L
->base
+ narg
-1;
96 lj_err_arg(L
, narg
, LJ_ERR_NOVAL
);
97 lj_cconv_ct_tv(cts
, ctype_get(cts
, CTID_INT32
), (uint8_t *)&i
, o
,
102 /* -- C type metamethods -------------------------------------------------- */
104 #define LJLIB_MODULE_ffi_meta
106 /* Handle ctype __index/__newindex metamethods. */
107 static int ffi_index_meta(lua_State
*L
, CTState
*cts
, CType
*ct
, MMS mm
)
109 CTypeID id
= ctype_typeid(cts
, ct
);
110 cTValue
*tv
= lj_ctype_meta(cts
, id
, mm
);
111 TValue
*base
= L
->base
;
115 s
= strdata(lj_ctype_repr(L
, id
, NULL
));
116 if (tvisstr(L
->base
+1)) {
117 lj_err_callerv(L
, LJ_ERR_FFI_BADMEMBER
, s
, strVdata(L
->base
+1));
119 const char *key
= tviscdata(L
->base
+1) ?
120 strdata(lj_ctype_repr(L
, cdataV(L
->base
+1)->ctypeid
, NULL
)) :
121 lj_typename(L
->base
+1);
122 lj_err_callerv(L
, LJ_ERR_FFI_BADIDXW
, s
, key
);
126 if (mm
== MM_index
) {
127 cTValue
*o
= lj_meta_tget(L
, tv
, base
+1);
129 if (tvisnil(o
)) goto err_index
;
130 copyTV(L
, L
->top
-1, o
);
134 TValue
*o
= lj_meta_tset(L
, tv
, base
+1);
136 copyTV(L
, o
, base
+2);
140 copyTV(L
, base
, L
->top
);
141 tv
= L
->top
-1-LJ_FR2
;
143 return lj_meta_tailcall(L
, tv
);
146 LJLIB_CF(ffi_meta___index
) LJLIB_REC(cdata_index
0)
148 CTState
*cts
= ctype_cts(L
);
153 if (!(o
+1 < L
->top
&& tviscdata(o
))) /* Also checks for presence of key. */
154 lj_err_argt(L
, 1, LUA_TCDATA
);
155 ct
= lj_cdata_index(cts
, cdataV(o
), o
+1, &p
, &qual
);
157 return ffi_index_meta(L
, cts
, ct
, MM_index
);
158 if (lj_cdata_get(cts
, ct
, L
->top
-1, p
))
163 LJLIB_CF(ffi_meta___newindex
) LJLIB_REC(cdata_index
1)
165 CTState
*cts
= ctype_cts(L
);
170 if (!(o
+2 < L
->top
&& tviscdata(o
))) /* Also checks for key and value. */
171 lj_err_argt(L
, 1, LUA_TCDATA
);
172 ct
= lj_cdata_index(cts
, cdataV(o
), o
+1, &p
, &qual
);
174 if ((qual
& CTF_CONST
))
175 lj_err_caller(L
, LJ_ERR_FFI_WRCONST
);
176 return ffi_index_meta(L
, cts
, ct
, MM_newindex
);
178 lj_cdata_set(cts
, ct
, p
, o
+2, qual
);
182 /* Common handler for cdata arithmetic. */
183 static int ffi_arith(lua_State
*L
)
185 MMS mm
= (MMS
)(curr_func(L
)->c
.ffid
- (int)FF_ffi_meta___eq
+ (int)MM_eq
);
186 return lj_carith_op(L
, mm
);
189 /* The following functions must be in contiguous ORDER MM. */
190 LJLIB_CF(ffi_meta___eq
) LJLIB_REC(cdata_arith MM_eq
)
195 LJLIB_CF(ffi_meta___len
) LJLIB_REC(cdata_arith MM_len
)
200 LJLIB_CF(ffi_meta___lt
) LJLIB_REC(cdata_arith MM_lt
)
205 LJLIB_CF(ffi_meta___le
) LJLIB_REC(cdata_arith MM_le
)
210 LJLIB_CF(ffi_meta___concat
) LJLIB_REC(cdata_arith MM_concat
)
215 /* Forward declaration. */
216 static int lj_cf_ffi_new(lua_State
*L
);
218 LJLIB_CF(ffi_meta___call
) LJLIB_REC(cdata_call
)
220 CTState
*cts
= ctype_cts(L
);
221 GCcdata
*cd
= ffi_checkcdata(L
, 1);
222 CTypeID id
= cd
->ctypeid
;
226 if (cd
->ctypeid
== CTID_CTYPEID
) {
227 id
= *(CTypeID
*)cdataptr(cd
);
230 int ret
= lj_ccall_func(L
, cd
);
234 /* Handle ctype __call/__new metamethod. */
235 ct
= ctype_raw(cts
, id
);
236 if (ctype_isptr(ct
->info
)) id
= ctype_cid(ct
->info
);
237 tv
= lj_ctype_meta(cts
, id
, mm
);
239 return lj_meta_tailcall(L
, tv
);
240 else if (mm
== MM_call
)
241 lj_err_callerv(L
, LJ_ERR_FFI_BADCALL
, strdata(lj_ctype_repr(L
, id
, NULL
)));
242 return lj_cf_ffi_new(L
);
245 LJLIB_CF(ffi_meta___add
) LJLIB_REC(cdata_arith MM_add
)
250 LJLIB_CF(ffi_meta___sub
) LJLIB_REC(cdata_arith MM_sub
)
255 LJLIB_CF(ffi_meta___mul
) LJLIB_REC(cdata_arith MM_mul
)
260 LJLIB_CF(ffi_meta___div
) LJLIB_REC(cdata_arith MM_div
)
265 LJLIB_CF(ffi_meta___mod
) LJLIB_REC(cdata_arith MM_mod
)
270 LJLIB_CF(ffi_meta___pow
) LJLIB_REC(cdata_arith MM_pow
)
275 LJLIB_CF(ffi_meta___unm
) LJLIB_REC(cdata_arith MM_unm
)
279 /* End of contiguous ORDER MM. */
281 LJLIB_CF(ffi_meta___tostring
)
283 GCcdata
*cd
= ffi_checkcdata(L
, 1);
284 const char *msg
= "cdata<%s>: %p";
285 CTypeID id
= cd
->ctypeid
;
286 void *p
= cdataptr(cd
);
287 if (id
== CTID_CTYPEID
) {
291 CTState
*cts
= ctype_cts(L
);
292 CType
*ct
= ctype_raw(cts
, id
);
293 if (ctype_isref(ct
->info
)) {
295 ct
= ctype_rawchild(cts
, ct
);
297 if (ctype_iscomplex(ct
->info
)) {
298 setstrV(L
, L
->top
-1, lj_ctype_repr_complex(L
, cdataptr(cd
), ct
->size
));
300 } else if (ct
->size
== 8 && ctype_isinteger(ct
->info
)) {
301 setstrV(L
, L
->top
-1, lj_ctype_repr_int64(L
, *(uint64_t *)cdataptr(cd
),
302 (ct
->info
& CTF_UNSIGNED
)));
304 } else if (ctype_isfunc(ct
->info
)) {
306 } else if (ctype_isenum(ct
->info
)) {
307 msg
= "cdata<%s>: %d";
308 p
= (void *)(uintptr_t)*(uint32_t **)p
;
310 if (ctype_isptr(ct
->info
)) {
311 p
= cdata_getptr(p
, ct
->size
);
312 ct
= ctype_rawchild(cts
, ct
);
314 if (ctype_isstruct(ct
->info
) || ctype_isvector(ct
->info
)) {
315 /* Handle ctype __tostring metamethod. */
316 cTValue
*tv
= lj_ctype_meta(cts
, ctype_typeid(cts
, ct
), MM_tostring
);
318 return lj_meta_tailcall(L
, tv
);
322 lj_strfmt_pushf(L
, msg
, strdata(lj_ctype_repr(L
, id
, NULL
)), p
);
328 static int ffi_pairs(lua_State
*L
, MMS mm
)
330 CTState
*cts
= ctype_cts(L
);
331 CTypeID id
= ffi_checkcdata(L
, 1)->ctypeid
;
332 CType
*ct
= ctype_raw(cts
, id
);
334 if (ctype_isptr(ct
->info
)) id
= ctype_cid(ct
->info
);
335 tv
= lj_ctype_meta(cts
, id
, mm
);
337 lj_err_callerv(L
, LJ_ERR_FFI_BADMM
, strdata(lj_ctype_repr(L
, id
, NULL
)),
338 strdata(mmname_str(G(L
), mm
)));
339 return lj_meta_tailcall(L
, tv
);
342 LJLIB_CF(ffi_meta___pairs
)
344 return ffi_pairs(L
, MM_pairs
);
347 LJLIB_CF(ffi_meta___ipairs
)
349 return ffi_pairs(L
, MM_ipairs
);
352 LJLIB_PUSH("ffi") LJLIB_SET(__metatable
)
354 #include "lj_libdef.h"
356 /* -- C library metamethods ----------------------------------------------- */
358 #define LJLIB_MODULE_ffi_clib
360 /* Index C library by a name. */
361 static TValue
*ffi_clib_index(lua_State
*L
)
365 if (!(o
< L
->top
&& tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_FFI_CLIB
))
366 lj_err_argt(L
, 1, LUA_TUSERDATA
);
367 cl
= (CLibrary
*)uddata(udataV(o
));
368 if (!(o
+1 < L
->top
&& tvisstr(o
+1)))
369 lj_err_argt(L
, 2, LUA_TSTRING
);
370 return lj_clib_index(L
, cl
, strV(o
+1));
373 LJLIB_CF(ffi_clib___index
) LJLIB_REC(clib_index
1)
375 TValue
*tv
= ffi_clib_index(L
);
377 CTState
*cts
= ctype_cts(L
);
378 GCcdata
*cd
= cdataV(tv
);
379 CType
*s
= ctype_get(cts
, cd
->ctypeid
);
380 if (ctype_isextern(s
->info
)) {
381 CTypeID sid
= ctype_cid(s
->info
);
382 void *sp
= *(void **)cdataptr(cd
);
383 CType
*ct
= ctype_raw(cts
, sid
);
384 if (lj_cconv_tv_ct(cts
, ct
, sid
, L
->top
-1, sp
))
389 copyTV(L
, L
->top
-1, tv
);
393 LJLIB_CF(ffi_clib___newindex
) LJLIB_REC(clib_index
0)
395 TValue
*tv
= ffi_clib_index(L
);
396 TValue
*o
= L
->base
+2;
397 if (o
< L
->top
&& tviscdata(tv
)) {
398 CTState
*cts
= ctype_cts(L
);
399 GCcdata
*cd
= cdataV(tv
);
400 CType
*d
= ctype_get(cts
, cd
->ctypeid
);
401 if (ctype_isextern(d
->info
)) {
403 for (;;) { /* Skip attributes and collect qualifiers. */
404 d
= ctype_child(cts
, d
);
405 if (!ctype_isattrib(d
->info
)) break;
406 if (ctype_attrib(d
->info
) == CTA_QUAL
) qual
|= d
->size
;
408 if (!((d
->info
|qual
) & CTF_CONST
)) {
409 lj_cconv_ct_tv(cts
, d
, *(void **)cdataptr(cd
), o
, 0);
414 lj_err_caller(L
, LJ_ERR_FFI_WRCONST
);
415 return 0; /* unreachable */
418 LJLIB_CF(ffi_clib___gc
)
421 if (o
< L
->top
&& tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_FFI_CLIB
)
422 lj_clib_unload((CLibrary
*)uddata(udataV(o
)));
426 #include "lj_libdef.h"
428 /* -- Callback function metamethods --------------------------------------- */
430 #define LJLIB_MODULE_ffi_callback
432 static int ffi_callback_set(lua_State
*L
, GCfunc
*fn
)
434 GCcdata
*cd
= ffi_checkcdata(L
, 1);
435 CTState
*cts
= ctype_cts(L
);
436 CType
*ct
= ctype_raw(cts
, cd
->ctypeid
);
437 if (ctype_isptr(ct
->info
) && (LJ_32
|| ct
->size
== 8)) {
438 MSize slot
= lj_ccallback_ptr2slot(cts
, *(void **)cdataptr(cd
));
439 if (slot
< cts
->cb
.sizeid
&& cts
->cb
.cbid
[slot
] != 0) {
440 GCtab
*t
= cts
->miscmap
;
441 TValue
*tv
= lj_tab_setint(L
, t
, (int32_t)slot
);
444 lj_gc_anybarriert(L
, t
);
447 cts
->cb
.cbid
[slot
] = 0;
448 cts
->cb
.topid
= slot
< cts
->cb
.topid
? slot
: cts
->cb
.topid
;
453 lj_err_caller(L
, LJ_ERR_FFI_BADCBACK
);
457 LJLIB_CF(ffi_callback_free
)
459 return ffi_callback_set(L
, NULL
);
462 LJLIB_CF(ffi_callback_set
)
464 GCfunc
*fn
= lj_lib_checkfunc(L
, 2);
465 return ffi_callback_set(L
, fn
);
468 LJLIB_PUSH(top
-1) LJLIB_SET(__index
)
470 #include "lj_libdef.h"
472 /* -- FFI library functions ----------------------------------------------- */
474 #define LJLIB_MODULE_ffi
478 GCstr
*s
= lj_lib_checkstr(L
, 1);
482 cp
.cts
= ctype_cts(L
);
483 cp
.srcname
= strdata(s
);
485 cp
.param
= L
->base
+1;
486 cp
.mode
= CPARSE_MODE_MULTI
|CPARSE_MODE_DIRECT
;
487 errcode
= lj_cparse(&cp
);
488 if (errcode
) lj_err_throw(L
, errcode
); /* Propagate errors. */
493 LJLIB_CF(ffi_new
) LJLIB_REC(.)
495 CTState
*cts
= ctype_cts(L
);
496 CTypeID id
= ffi_checkctype(L
, cts
, NULL
);
497 CType
*ct
= ctype_raw(cts
, id
);
499 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
500 TValue
*o
= L
->base
+1;
502 if ((info
& CTF_VLA
)) {
504 sz
= lj_ctype_vlsize(cts
, ct
, (CTSize
)ffi_checkint(L
, 2));
506 if (sz
== CTSIZE_INVALID
)
507 lj_err_arg(L
, 1, LJ_ERR_FFI_INVSIZE
);
508 cd
= lj_cdata_newx(cts
, id
, sz
, info
);
509 setcdataV(L
, o
-1, cd
); /* Anchor the uninitialized cdata. */
510 lj_cconv_ct_init(cts
, ct
, sz
, cdataptr(cd
),
511 o
, (MSize
)(L
->top
- o
)); /* Initialize cdata. */
512 if (ctype_isstruct(ct
->info
)) {
513 /* Handle ctype __gc metamethod. Use the fast lookup here. */
514 cTValue
*tv
= lj_tab_getinth(cts
->miscmap
, -(int32_t)id
);
515 if (tv
&& tvistab(tv
) && (tv
= lj_meta_fast(L
, tabV(tv
), MM_gc
))) {
516 GCtab
*t
= tabref(G(L
)->gcroot
[GCROOT_FFI_FIN
]);
517 if (gcref(t
->metatable
)) {
518 /* Add to finalizer table, if still enabled. */
519 copyTV(L
, lj_tab_set(L
, t
, o
-1), tv
);
520 lj_gc_anybarriert(L
, t
);
521 cd
->marked
|= LJ_GC_CDATA_FIN
;
525 L
->top
= o
; /* Only return the cdata itself. */
530 LJLIB_CF(ffi_cast
) LJLIB_REC(ffi_new
)
532 CTState
*cts
= ctype_cts(L
);
533 CTypeID id
= ffi_checkctype(L
, cts
, NULL
);
534 CType
*d
= ctype_raw(cts
, id
);
535 TValue
*o
= lj_lib_checkany(L
, 2);
536 L
->top
= o
+1; /* Make sure this is the last item on the stack. */
537 if (!(ctype_isnum(d
->info
) || ctype_isptr(d
->info
) || ctype_isenum(d
->info
)))
538 lj_err_arg(L
, 1, LJ_ERR_FFI_INVTYPE
);
539 if (!(tviscdata(o
) && cdataV(o
)->ctypeid
== id
)) {
540 GCcdata
*cd
= lj_cdata_new(cts
, id
, d
->size
);
541 lj_cconv_ct_tv(cts
, d
, cdataptr(cd
), o
, CCF_CAST
);
548 LJLIB_CF(ffi_typeof
) LJLIB_REC(.)
550 CTState
*cts
= ctype_cts(L
);
551 CTypeID id
= ffi_checkctype(L
, cts
, L
->base
+1);
552 GCcdata
*cd
= lj_cdata_new(cts
, CTID_CTYPEID
, 4);
553 *(CTypeID
*)cdataptr(cd
) = id
;
554 setcdataV(L
, L
->top
-1, cd
);
559 /* Internal and unsupported API. */
560 LJLIB_CF(ffi_typeinfo
)
562 CTState
*cts
= ctype_cts(L
);
563 CTypeID id
= (CTypeID
)ffi_checkint(L
, 1);
564 if (id
> 0 && id
< cts
->top
) {
565 CType
*ct
= ctype_get(cts
, id
);
567 lua_createtable(L
, 0, 4); /* Increment hash size if fields are added. */
569 setintV(lj_tab_setstr(L
, t
, lj_str_newlit(L
, "info")), (int32_t)ct
->info
);
570 if (ct
->size
!= CTSIZE_INVALID
)
571 setintV(lj_tab_setstr(L
, t
, lj_str_newlit(L
, "size")), (int32_t)ct
->size
);
573 setintV(lj_tab_setstr(L
, t
, lj_str_newlit(L
, "sib")), (int32_t)ct
->sib
);
574 if (gcref(ct
->name
)) {
575 GCstr
*s
= gco2str(gcref(ct
->name
));
576 if (isdead(G(L
), obj2gco(s
))) flipwhite(obj2gco(s
));
577 setstrV(L
, lj_tab_setstr(L
, t
, lj_str_newlit(L
, "name")), s
);
585 LJLIB_CF(ffi_istype
) LJLIB_REC(.)
587 CTState
*cts
= ctype_cts(L
);
588 CTypeID id1
= ffi_checkctype(L
, cts
, NULL
);
589 TValue
*o
= lj_lib_checkany(L
, 2);
592 GCcdata
*cd
= cdataV(o
);
593 CTypeID id2
= cd
->ctypeid
== CTID_CTYPEID
? *(CTypeID
*)cdataptr(cd
) :
595 CType
*ct1
= lj_ctype_rawref(cts
, id1
);
596 CType
*ct2
= lj_ctype_rawref(cts
, id2
);
599 } else if (ctype_type(ct1
->info
) == ctype_type(ct2
->info
) &&
600 ct1
->size
== ct2
->size
) {
601 if (ctype_ispointer(ct1
->info
))
602 b
= lj_cconv_compatptr(cts
, ct1
, ct2
, CCF_IGNQUAL
);
603 else if (ctype_isnum(ct1
->info
) || ctype_isvoid(ct1
->info
))
604 b
= (((ct1
->info
^ ct2
->info
) & ~(CTF_QUAL
|CTF_LONG
)) == 0);
605 } else if (ctype_isstruct(ct1
->info
) && ctype_isptr(ct2
->info
) &&
606 ct1
== ctype_rawchild(cts
, ct2
)) {
610 setboolV(L
->top
-1, b
);
611 setboolV(&G(L
)->tmptv2
, b
); /* Remember for trace recorder. */
615 LJLIB_CF(ffi_sizeof
) LJLIB_REC(ffi_xof FF_ffi_sizeof
)
617 CTState
*cts
= ctype_cts(L
);
618 CTypeID id
= ffi_checkctype(L
, cts
, NULL
);
620 if (LJ_UNLIKELY(tviscdata(L
->base
) && cdataisv(cdataV(L
->base
)))) {
621 sz
= cdatavlen(cdataV(L
->base
));
623 CType
*ct
= lj_ctype_rawref(cts
, id
);
624 if (ctype_isvltype(ct
->info
))
625 sz
= lj_ctype_vlsize(cts
, ct
, (CTSize
)ffi_checkint(L
, 2));
627 sz
= ctype_hassize(ct
->info
) ? ct
->size
: CTSIZE_INVALID
;
628 if (LJ_UNLIKELY(sz
== CTSIZE_INVALID
)) {
633 setintV(L
->top
-1, (int32_t)sz
);
637 LJLIB_CF(ffi_alignof
) LJLIB_REC(ffi_xof FF_ffi_alignof
)
639 CTState
*cts
= ctype_cts(L
);
640 CTypeID id
= ffi_checkctype(L
, cts
, NULL
);
642 CTInfo info
= lj_ctype_info_raw(cts
, id
, &sz
);
643 setintV(L
->top
-1, 1 << ctype_align(info
));
647 LJLIB_CF(ffi_offsetof
) LJLIB_REC(ffi_xof FF_ffi_offsetof
)
649 CTState
*cts
= ctype_cts(L
);
650 CTypeID id
= ffi_checkctype(L
, cts
, NULL
);
651 GCstr
*name
= lj_lib_checkstr(L
, 2);
652 CType
*ct
= lj_ctype_rawref(cts
, id
);
654 if (ctype_isstruct(ct
->info
) && ct
->size
!= CTSIZE_INVALID
) {
655 CType
*fct
= lj_ctype_getfield(cts
, ct
, name
, &ofs
);
657 setintV(L
->top
-1, ofs
);
658 if (ctype_isfield(fct
->info
)) {
660 } else if (ctype_isbitfield(fct
->info
)) {
661 setintV(L
->top
++, ctype_bitpos(fct
->info
));
662 setintV(L
->top
++, ctype_bitbsz(fct
->info
));
670 LJLIB_CF(ffi_errno
) LJLIB_REC(.)
673 if (L
->top
> L
->base
)
674 errno
= ffi_checkint(L
, 1);
675 setintV(L
->top
++, err
);
679 LJLIB_CF(ffi_string
) LJLIB_REC(.)
681 CTState
*cts
= ctype_cts(L
);
682 TValue
*o
= lj_lib_checkany(L
, 1);
685 if (o
+1 < L
->top
&& !tvisnil(o
+1)) {
686 len
= (size_t)ffi_checkint(L
, 2);
687 lj_cconv_ct_tv(cts
, ctype_get(cts
, CTID_P_CVOID
), (uint8_t *)&p
, o
,
690 lj_cconv_ct_tv(cts
, ctype_get(cts
, CTID_P_CCHAR
), (uint8_t *)&p
, o
,
694 L
->top
= o
+1; /* Make sure this is the last item on the stack. */
695 setstrV(L
, o
, lj_str_new(L
, p
, len
));
700 LJLIB_CF(ffi_copy
) LJLIB_REC(.)
702 void *dp
= ffi_checkptr(L
, 1, CTID_P_VOID
);
703 void *sp
= ffi_checkptr(L
, 2, CTID_P_CVOID
);
704 TValue
*o
= L
->base
+1;
706 if (tvisstr(o
) && o
+1 >= L
->top
)
707 len
= strV(o
)->len
+1; /* Copy Lua string including trailing '\0'. */
709 len
= (CTSize
)ffi_checkint(L
, 3);
714 LJLIB_CF(ffi_fill
) LJLIB_REC(.)
716 void *dp
= ffi_checkptr(L
, 1, CTID_P_VOID
);
717 CTSize len
= (CTSize
)ffi_checkint(L
, 2);
719 if (L
->base
+2 < L
->top
&& !tvisnil(L
->base
+2)) fill
= ffi_checkint(L
, 3);
720 memset(dp
, fill
, len
);
724 /* Test ABI string. */
725 LJLIB_CF(ffi_abi
) LJLIB_REC(.)
727 GCstr
*s
= lj_lib_checkstr(L
, 1);
728 int b
= lj_cparse_case(s
,
763 setboolV(L
->top
-1, b
);
764 setboolV(&G(L
)->tmptv2
, b
); /* Remember for trace recorder. */
768 LJLIB_PUSH(top
-7) LJLIB_SET(!) /* Store reference to miscmap table. */
770 LJLIB_CF(ffi_metatype
)
772 CTState
*cts
= ctype_cts(L
);
773 CTypeID id
= ffi_checkctype(L
, cts
, NULL
);
774 GCtab
*mt
= lj_lib_checktab(L
, 2);
775 GCtab
*t
= cts
->miscmap
;
776 CType
*ct
= ctype_raw(cts
, id
);
779 if (!(ctype_isstruct(ct
->info
) || ctype_iscomplex(ct
->info
) ||
780 ctype_isvector(ct
->info
)))
781 lj_err_arg(L
, 1, LJ_ERR_FFI_INVTYPE
);
782 tv
= lj_tab_setinth(L
, t
, -(int32_t)ctype_typeid(cts
, ct
));
784 lj_err_caller(L
, LJ_ERR_PROTMT
);
786 lj_gc_anybarriert(L
, t
);
787 cd
= lj_cdata_new(cts
, CTID_CTYPEID
, 4);
788 *(CTypeID
*)cdataptr(cd
) = id
;
789 setcdataV(L
, L
->top
-1, cd
);
794 LJLIB_CF(ffi_gc
) LJLIB_REC(.)
796 GCcdata
*cd
= ffi_checkcdata(L
, 1);
797 TValue
*fin
= lj_lib_checkany(L
, 2);
798 CTState
*cts
= ctype_cts(L
);
799 CType
*ct
= ctype_raw(cts
, cd
->ctypeid
);
800 if (!(ctype_isptr(ct
->info
) || ctype_isstruct(ct
->info
) ||
801 ctype_isrefarray(ct
->info
)))
802 lj_err_arg(L
, 1, LJ_ERR_FFI_INVTYPE
);
803 lj_cdata_setfin(L
, cd
, gcval(fin
), itype(fin
));
804 L
->top
= L
->base
+1; /* Pass through the cdata object. */
808 LJLIB_PUSH(top
-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
812 GCstr
*name
= lj_lib_checkstr(L
, 1);
813 int global
= (L
->base
+1 < L
->top
&& tvistruecond(L
->base
+1));
814 lj_clib_load(L
, tabref(curr_func(L
)->c
.env
), name
, global
);
818 LJLIB_PUSH(top
-4) LJLIB_SET(C
)
819 LJLIB_PUSH(top
-3) LJLIB_SET(os
)
820 LJLIB_PUSH(top
-2) LJLIB_SET(arch
)
822 #include "lj_libdef.h"
824 /* ------------------------------------------------------------------------ */
826 /* Register FFI module as loaded. */
827 static void ffi_register_module(lua_State
*L
)
829 cTValue
*tmp
= lj_tab_getstr(tabV(registry(L
)), lj_str_newlit(L
, "_LOADED"));
830 if (tmp
&& tvistab(tmp
)) {
831 GCtab
*t
= tabV(tmp
);
832 copyTV(L
, lj_tab_setstr(L
, t
, lj_str_newlit(L
, LUA_FFILIBNAME
)), L
->top
-1);
833 lj_gc_anybarriert(L
, t
);
837 LUALIB_API
int luaopen_ffi(lua_State
*L
)
839 CTState
*cts
= lj_ctype_init(L
);
840 settabV(L
, L
->top
++, (cts
->miscmap
= lj_tab_new(L
, 0, 1)));
841 LJ_LIB_REG(L
, NULL
, ffi_meta
);
842 /* NOBARRIER: basemt is a GC root. */
843 setgcref(basemt_it(G(L
), LJ_TCDATA
), obj2gco(tabV(L
->top
-1)));
844 LJ_LIB_REG(L
, NULL
, ffi_clib
);
845 LJ_LIB_REG(L
, NULL
, ffi_callback
);
846 /* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */
847 settabV(L
, lj_tab_setstr(L
, cts
->miscmap
, &cts
->g
->strempty
), tabV(L
->top
-1));
849 lj_clib_default(L
, tabV(L
->top
-1)); /* Create ffi.C default namespace. */
850 lua_pushliteral(L
, LJ_OS_NAME
);
851 lua_pushliteral(L
, LJ_ARCH_NAME
);
852 LJ_LIB_REG(L
, NULL
, ffi
); /* Note: no global "ffi" created! */
853 ffi_register_module(L
);