static SQInteger sq_lib_bind_var(HSQUIRRELVM v) { void **modbuf; void *mod; void *sym; const SQChar *symname; const char *type; sq_getuserdata(v, 1, (void**)&modbuf, NULL); mod = *modbuf; sq_getstring(v, 2, &type); sq_getstring(v, 3, &symname); sym = GET_SYM(mod, symname); if (!sym) return sq_throwerror(v, "Cannot find symbol"); FFIVar *ffibuf = (FFIVar*)sq_newuserdata(v, sizeof(FFIVar)); sq_push_delegate_table(v, FFI_LIB_VAR_TAG); sq_setdelegate(v, -2); ffibuf->var = sym; ffibuf->type = *type; return 1; }
inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = NULL; SQUserPointer real_instance = NULL; HSQOBJECT instance; /* Get the 'SQ' instance of this class */ Squirrel::GetInstance(vm, &instance); /* Protect against calls to a non-static method in a static way */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, 0); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, 0); if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); /* Remove the userdata from the stack */ sq_pop(vm, 1); /* Call the function, which its only param is always the VM */ return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm); }
inline SQInteger DefSQNonStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = NULL; SQUserPointer real_instance = NULL; HSQOBJECT instance; /* Get the 'SQ' instance of this class */ Squirrel::GetInstance(vm, &instance); /* Protect against calls to a non-static method in a static way */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, 0); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, 0); if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); /* Remove the userdata from the stack */ sq_pop(vm, 1); try { /* Delegate it to a template that can handle this specific function */ return HelperT<Tmethod>::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm); } catch (SQInteger e) { sq_pop(vm, nparam); return e; } }
static void demarshal(HSQUIRRELVM vm, IndexPack<I...> indices) { T* instance = nullptr; void (T::**method)(A...) = nullptr; sq_getinstanceup(vm, 1, (SQUserPointer*) &instance, nullptr); sq_getuserdata(vm, -1, (SQUserPointer*) &method, nullptr); (instance->**method)(detail::get<A>(vm, I + 2)...); }
inline SQInteger DefSQStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = NULL; /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, 0); try { /* Delegate it to a template that can handle this specific function */ return HelperT<Tmethod>::SQCall((Tcls *)NULL, *(Tmethod *)ptr, vm); } catch (SQInteger e) { sq_pop(vm, nparam); return e; } }
static SQInteger sq_lib_bind_func(HSQUIRRELVM v) { void **modbuf; void *mod; void *sym; const SQChar *symname; const char *rettype; sq_getuserdata(v, 1, (void**)&modbuf, NULL); mod = *modbuf; sq_getstring(v, 2, &rettype); sq_getstring(v, 3, &symname); sym = GET_SYM(mod, symname); if (!sym) return sq_throwerror(v, "Cannot find symbol"); int nparam = sq_getsize(v, 4); int size = sizeof(FFIFunc) + sizeof(ffi_type*) * nparam; FFIFunc *ffibuf = (FFIFunc*)sq_newuserdata(v, size); sq_push_delegate_table(v, FFI_LIB_FUNC_TAG); sq_setdelegate(v, -2); // printf("Allocated %d bytes at %p\n", size, ffibuf); ffibuf->func = sym; ffibuf->rettype = *rettype; int i; for (i = 0; i < nparam; i++) { sq_pushinteger(v, i); sq_get(v, 4); ffibuf->params[i] = get_ffi_type(v, -1); if (!ffibuf->params[i]) return SQ_ERROR; sq_poptop(v); } int res = ffi_prep_cif(&ffibuf->cif, FFI_DEFAULT_ABI, nparam, char2ffi_type(*rettype), ffibuf->params); if (res != FFI_OK) return sq_throwerror(v, "Error in ffi_prep_cif"); return 1; }
static SQInteger sq_func__call(HSQUIRRELVM v) { FFIFunc *ffibuf; sq_getuserdata(v, 1, (void**)&ffibuf, NULL); int top = sq_gettop(v); // printf("ffibuf %p top %d\n", ffibuf, top); if (ffibuf->cif.nargs != ((unsigned)(top - EXTRA_PARAMS))) return sq_throwerror(v, "Wrong number of args"); SQInteger values[top - EXTRA_PARAMS]; void *valueptrs[top - EXTRA_PARAMS]; int i; for (i = EXTRA_PARAMS + 1; i <= top; i++) { #define pi (i - (EXTRA_PARAMS + 1)) switch (sq_gettype(v, i)) { case OT_INTEGER: sq_getinteger(v, i, (SQInteger*)&values[pi]); break; case OT_STRING: sq_getstring(v, i, (const char**)&values[pi]); break; case OT_INSTANCE: { if (SQ_FAILED(sqstd_getblob(v, i, (SQUserPointer*)&values[pi]))) return SQ_ERROR; break; } default: return sq_throwerror(v, "Unimplemented type"); } valueptrs[pi] = &values[pi]; } ptrdiff_t rc; // printf("Before call, %p\n", ffibuf->func); ffi_call(&ffibuf->cif, (void(*)())ffibuf->func, &rc, valueptrs); return_ffi_value(v, rc, ffibuf->rettype); return 1; }
static SQInteger sq_var_get(HSQUIRRELVM v) { FFIVar *ffibuf; sq_getuserdata(v, 1, (void**)&ffibuf, NULL); void *pval = ffibuf->var; switch (ffibuf->type) { case 's': sq_pushstring(v, *(char**)pval, -1); break; case 'i': sq_pushinteger(v, *(int*)pval); break; case 'I': sq_pushinteger(v, *(unsigned int*)pval); break; case 'h': sq_pushinteger(v, *(short*)pval); break; case 'H': sq_pushinteger(v, *(unsigned short*)pval); break; case 'l': sq_pushinteger(v, *(long*)pval); break; case 'L': sq_pushinteger(v, *(unsigned long*)pval); break; case 'b': sq_pushinteger(v, *(char*)pval); break; case 'B': sq_pushinteger(v, *(unsigned char*)pval); break; default: sq_pushinteger(v, *(int*)pval); } return 1; }
static void demarshal(HSQUIRRELVM vm, IndexPack<I...> indices) { void (**function)(A...) = nullptr; sq_getuserdata(vm, -1, (SQUserPointer*) &function, nullptr); (*function)(detail::get<A>(vm, I + 1)...); }