ikptr_t ikrt_ffi_release_callback (ikptr_t s_callable_pointer, ikpcb_t * pcb) { ik_callback_locative_t * root; void * callable_pointer; root = pcb->callbacks; callable_pointer = IK_POINTER_DATA_VOIDP(s_callable_pointer); if (root) { if (root->callable_pointer == callable_pointer) { pcb->callbacks = root->next; ffi_closure_free(root->closure); free(root); return IK_TRUE_OBJECT; } else { for (; root->next; root = root->next) { if (root->next->callable_pointer != callable_pointer) continue; else { ik_callback_locative_t * this = root->next; root->next = root->next->next; ffi_closure_free(this->closure); free(this); return IK_TRUE_OBJECT; } } return IK_FALSE_OBJECT; } } else return IK_TRUE_OBJECT; }
/* * There are some resources that accumulate over the life of the Lua VM. The reason * why we cannot collect these during the VM's lifetime is because it's impossible * to determine when they are no longer needed, and because it's not plausible * to rely on Lua code (as it is untrusted) to close these resources. * * So, we have to close them at the end of the lifecycle. */ void engine_close(JNIEnv* env, engine_inst* inst) { // close lua entirely lua_close(inst->state); // if the engine was already marked closed, do nothing if (inst->closed) return; // Free all function wrappers (and underlying ffi closures). // the amount of closures registered will continue to grow as // java functions are registered, and will only be free'd when // the entire engine is closed. int t; for (t = 0; t < inst->wrappers_amt; t++) { freewrapper(inst, env, inst->wrappers[t]); } // free wrapper stack if (inst->wrappers) { free(inst->wrappers); inst->wrappers = 0; } inst->wrappers_amt = 0; // free closure used for hook function ffi_closure_free(inst->closure); // free instance struct free(inst); }
void free_callback(JNIEnv* env, callback *cb) { int i; (*env)->DeleteWeakGlobalRef(env, cb->object); ffi_closure_free(cb->closure); free(cb->arg_types); if (cb->arg_classes) { unsigned i; for (i=0;i < cb->cif.nargs;i++) { if (cb->arg_classes[i]) { (*env)->DeleteWeakGlobalRef(env, cb->arg_classes[i]); } } free(cb->arg_classes); } free(cb->java_arg_types); if (cb->conversion_flags) { free(cb->conversion_flags); } free(cb->arg_jtypes); #ifdef DLL_FPTRS for (i=0;i < DLL_FPTRS;i++) { if (fn[i] == cb->saved_x_closure) { fn[i] = NULL; } } #endif free((void *)cb->encoding); free(cb); }
/** * g_callable_info_prepare_closure: * @callable_info: a callable info from a typelib * @cif: a ffi_cif structure * @callback: the ffi callback * @user_data: data to be passed into the callback * * Prepares a callback for ffi invocation. * * Return value: the ffi_closure or NULL on error. * The return value should be freed by calling g_callable_info_free_closure(). */ ffi_closure * g_callable_info_prepare_closure (GICallableInfo *callable_info, ffi_cif *cif, GIFFIClosureCallback callback, gpointer user_data) { gpointer exec_ptr; GIClosureWrapper *closure; ffi_status status; g_return_val_if_fail (callable_info != NULL, FALSE); g_return_val_if_fail (cif != NULL, FALSE); g_return_val_if_fail (callback != NULL, FALSE); closure = ffi_closure_alloc (sizeof (GIClosureWrapper), &exec_ptr); if (!closure) { g_warning ("could not allocate closure\n"); return NULL; } closure->writable_self = closure; status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, g_callable_info_get_n_args (callable_info), g_callable_info_get_ffi_return_type (callable_info), g_callable_info_get_ffi_arg_types (callable_info)); if (status != FFI_OK) { g_warning ("ffi_prep_cif failed: %d\n", status); ffi_closure_free (closure); return NULL; } status = ffi_prep_closure_loc (&closure->ffi_closure, cif, callback, user_data, exec_ptr); if (status != FFI_OK) { g_warning ("ffi_prep_closure failed: %d\n", status); ffi_closure_free (closure); return NULL; } /* Return exec_ptr, which points to the same underlying memory as * closure, but via an executable-non-writable mapping. */ return exec_ptr; }
// freeExec gets passed the executable address, not the writable address. void freeExec (AdjustorExecutable addr) { AdjustorWritable writable; writable = *((void**)addr - 1); ACQUIRE_SM_LOCK; ffi_closure_free (writable); RELEASE_SM_LOCK }
/** * g_callable_info_free_closure: * @callable_info: a callable info from a typelib * @closure: ffi closure * * Frees a ffi_closure returned from g_callable_info_prepare_closure() */ void g_callable_info_free_closure (GICallableInfo *callable_info, ffi_closure *closure) { GIClosureWrapper *wrapper = (GIClosureWrapper *)closure; g_free (wrapper->ffi_closure.cif->arg_types); ffi_closure_free (wrapper->writable_self); }
void freeExec(AdjustorExecutable exec) { AdjustorWritable writ; ffi_closure* cl; cl = writ = execToWritable(exec); ACQUIRE_SM_LOCK; removeHashTable(allocatedExecs, (StgWord)exec, writ); ffi_closure_free(cl); RELEASE_SM_LOCK }
static void CThunkObject_dealloc(PyObject *_self) { CThunkObject *self = (CThunkObject *)_self; Py_XDECREF(self->converters); Py_XDECREF(self->callable); Py_XDECREF(self->restype); if (self->pcl_write) ffi_closure_free(self->pcl_write); PyObject_GC_Del(self); }
static void cfunc_closure_destructor(mrb_state *mrb, void *p_) { struct cfunc_closure_data *p = p_; if (p->closure) { ffi_closure_free(p->closure); } mrb_free(mrb, p->arg_types); mrb_free(mrb, p->arg_ffi_types); mrb_free(mrb, p->cif); mrb_free(mrb, p); }
cl_object si_free_ffi_closure(cl_object closure) { ffi_closure_free(ecl_foreign_data_pointer_safe(closure)); { #line 985 const cl_env_ptr the_env = ecl_process_env(); the_env->nvalues = 0; return ECL_NIL; #line 985 } ; }
static void dealloc(void * ptr) { fiddle_closure * cls = (fiddle_closure *)ptr; #ifndef DONT_USE_FFI_CLOSURE_ALLOC ffi_closure_free(cls->pcl); #else munmap(cls->pcl, sizeof(cls->pcl)); #endif if (cls->argv) xfree(cls->argv); xfree(cls); }
static void function_free(Function *fn) { if (fn->methodHandle != NULL) { rbffi_MethodHandle_Free(fn->methodHandle); } if (fn->ffiClosure != NULL && fn->autorelease) { ffi_closure_free(fn->ffiClosure); } xfree(fn); }
static VALUE function_release(VALUE self) { Function* fn; Data_Get_Struct(self, Function, fn); if (fn->ffiClosure == NULL) { rb_raise(rb_eRuntimeError, "cannot free function which was not allocated"); } ffi_closure_free(fn->ffiClosure); fn->ffiClosure = NULL; return self; }
void free_callback(JNIEnv* env, callback *cb) { (*env)->DeleteWeakGlobalRef(env, cb->object); ffi_closure_free(cb->closure); free(cb->arg_types); if (cb->arg_classes) { unsigned i; for (i=0;i < cb->cif.nargs;i++) { (*env)->DeleteWeakGlobalRef(env, cb->arg_classes[i]); } free(cb->arg_classes); } free(cb->java_arg_types); if (cb->flags) free(cb->flags); free(cb->arg_jtypes); free(cb); }
static void freewrapper(engine_inst* inst, JNIEnv* env, engine_jfuncwrapper* wrapper) { // free closure ffi_closure_free(wrapper->closure); // delete global reference to java function if (wrapper->obj_inst) { // if it's null, it was for a reflected static function (*env)->DeleteGlobalRef(env, wrapper->obj_inst); } // reflected methods have a Method instance to be deleted if (wrapper->type == ENGINE_JAVA_REFLECT_FUNCTION) { (*env)->DeleteGlobalRef(env, wrapper->data.reflect.method); } else if (wrapper->type == ENGINE_JAVA_LAMBDA_FUNCTION) { (*env)->DeleteGlobalRef(env, wrapper->data.lambda.class_array); } free(wrapper); }
int main() { ffi_cif cif; ffi_type *args[1]; ffi_closure *closure; int (*bound_puts)(char *); int rc; /* Allocate closure and bound_puts */ closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts); if (closure) { /* Initialize the argument info vectors */ args[0] = &ffi_type_pointer; /* Initialize the cif */ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args) == FFI_OK) { /* Initialize the closure, setting stream to stdout */ if (ffi_prep_closure_loc(closure, &cif, puts_binding, stdout, bound_puts) == FFI_OK) { rc = bound_puts("Hello World!"); /* rc now holds the result of the call to fputs */ } } } /* Deallocate both closure, and bound_puts */ ffi_closure_free(closure); return 0; }
FFIData::~FFIData() { free(arg_types); XFREE(cif.arg_types); if(closure) ffi_closure_free(closure); }
FFIData::~FFIData() { if(args_info) XFREE(args_info); if(cif.arg_types) XFREE(cif.arg_types); if(closure) ffi_closure_free(closure); }
Handle poly_ffi(TaskData *taskData, Handle args, Handle code) { unsigned c = get_C_unsigned(taskData, code->Word()); switch (c) { case 0: // malloc { POLYUNSIGNED size = getPolyUnsigned(taskData, args->Word()); return toSysWord(taskData, malloc(size)); } case 1: // free { void *mem = *(void**)(args->WordP()); free(mem); return taskData->saveVec.push(TAGGED(0)); } case 2: // Load library { TempString libName(args->Word()); #if (defined(_WIN32) && ! defined(__CYGWIN__)) HINSTANCE lib = LoadLibrary(libName); if (lib == NULL) { char buf[256]; #if (defined(UNICODE)) _snprintf(buf, sizeof(buf), "Loading <%S> failed. Error %lu", libName, GetLastError()); #else _snprintf(buf, sizeof(buf), "Loading <%s> failed. Error %lu", libName, GetLastError()); #endif buf[sizeof(buf)-1] = 0; // Terminate just in case raise_exception_string(taskData, EXC_foreign, buf); } #else void *lib = dlopen(libName, RTLD_LAZY); if (lib == NULL) { char buf[256]; snprintf(buf, sizeof(buf), "Loading <%s> failed: %s", (const char *)libName, dlerror()); buf[sizeof(buf)-1] = 0; // Terminate just in case raise_exception_string(taskData, EXC_foreign, buf); } #endif return toSysWord(taskData, lib); } case 3: // Load address of executable. { #if (defined(_WIN32) && ! defined(__CYGWIN__)) HINSTANCE lib = hApplicationInstance; #else void *lib = dlopen(NULL, RTLD_LAZY); if (lib == NULL) { char buf[256]; snprintf(buf, sizeof(buf), "Loading address of executable failed: %s", dlerror()); buf[sizeof(buf)-1] = 0; // Terminate just in case raise_exception_string(taskData, EXC_foreign, buf); } #endif return toSysWord(taskData, lib); } case 4: // Unload library - Is this actually going to be used? { #if (defined(_WIN32) && ! defined(__CYGWIN__)) HMODULE hMod = *(HMODULE*)(args->WordP()); if (! FreeLibrary(hMod)) raise_syscall(taskData, "FreeLibrary failed", -(int)GetLastError()); #else void *lib = *(void**)(args->WordP()); if (dlclose(lib) != 0) { char buf[256]; snprintf(buf, sizeof(buf), "dlclose failed: %s", dlerror()); buf[sizeof(buf)-1] = 0; // Terminate just in case raise_exception_string(taskData, EXC_foreign, buf); } #endif return taskData->saveVec.push(TAGGED(0)); } case 5: // Load the address of a symbol from a library. { TempCString symName(args->WordP()->Get(1)); #if (defined(_WIN32) && ! defined(__CYGWIN__)) HMODULE hMod = *(HMODULE*)(args->WordP()->Get(0).AsAddress()); void *sym = (void*)GetProcAddress(hMod, symName); if (sym == NULL) { char buf[256]; _snprintf(buf, sizeof(buf), "Loading symbol <%s> failed. Error %lu", symName, GetLastError()); buf[sizeof(buf)-1] = 0; // Terminate just in case raise_exception_string(taskData, EXC_foreign, buf); } #else void *lib = *(void**)(args->WordP()->Get(0).AsAddress()); void *sym = dlsym(lib, symName); if (sym == NULL) { char buf[256]; snprintf(buf, sizeof(buf), "load_sym <%s> : %s", (const char *)symName, dlerror()); buf[sizeof(buf)-1] = 0; // Terminate just in case raise_exception_string(taskData, EXC_foreign, buf); } #endif return toSysWord(taskData, sym); } // Libffi functions case 50: // Return a list of available ABIs return makeList(taskData, sizeof(abiTable)/sizeof(abiTable[0]), (char*)abiTable, sizeof(abiTable[0]), 0, mkAbitab); case 51: // A constant from the table { unsigned index = get_C_unsigned(taskData, args->Word()); if (index >= sizeof(constantTable) / sizeof(constantTable[0])) raise_exception_string(taskData, EXC_foreign, "Index out of range"); return Make_arbitrary_precision(taskData, constantTable[index]); } case 52: // Return an FFI type { unsigned index = get_C_unsigned(taskData, args->Word()); if (index >= sizeof(ffiTypeTable) / sizeof(ffiTypeTable[0])) raise_exception_string(taskData, EXC_foreign, "Index out of range"); return toSysWord(taskData, ffiTypeTable[index]); } case 53: // Extract fields from ffi type. { ffi_type *ffit = *(ffi_type**)(args->WordP()); Handle sizeHandle = Make_arbitrary_precision(taskData, ffit->size); Handle alignHandle = Make_arbitrary_precision(taskData, ffit->alignment); Handle typeHandle = Make_arbitrary_precision(taskData, ffit->type); Handle elemHandle = toSysWord(taskData, ffit->elements); Handle resHandle = alloc_and_save(taskData, 4); resHandle->WordP()->Set(0, sizeHandle->Word()); resHandle->WordP()->Set(1, alignHandle->Word()); resHandle->WordP()->Set(2, typeHandle->Word()); resHandle->WordP()->Set(3, elemHandle->Word()); return resHandle; } case 54: // Construct an ffi type. { // This is probably only used to create structs. size_t size = getPolyUnsigned(taskData, args->WordP()->Get(0)); unsigned short align = get_C_ushort(taskData, args->WordP()->Get(1)); unsigned short type = get_C_ushort(taskData, args->WordP()->Get(2)); unsigned nElems = 0; for (PolyWord p = args->WordP()->Get(3); !ML_Cons_Cell::IsNull(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t) nElems++; size_t space = sizeof(ffi_type); // If we need the elements add space for the elements plus // one extra for the zero terminator. if (nElems != 0) space += (nElems+1) * sizeof(ffi_type *); ffi_type *result = (ffi_type*)malloc(space); // Raise an exception rather than returning zero. if (result == 0) raise_syscall(taskData, "Insufficient memory", ENOMEM); ffi_type **elem = 0; if (nElems != 0) elem = (ffi_type **)(result+1); memset(result, 0, sizeof(ffi_type)); // Zero it in case they add fields result->size = size; result->alignment = align; result->type = type; result->elements = elem; if (elem != 0) { for (PolyWord p = args->WordP()->Get(3); !ML_Cons_Cell::IsNull(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t) { PolyWord e = ((ML_Cons_Cell*)p.AsObjPtr())->h; *elem++ = *(ffi_type**)(e.AsAddress()); } *elem = 0; } return toSysWord(taskData, result); } case 55: // Create a CIF. This contains all the types and some extra information. // The result is in allocated memory followed immediately by the argument type vector. { ffi_abi abi = (ffi_abi)get_C_ushort(taskData, args->WordP()->Get(0)); ffi_type *rtype = *(ffi_type **)args->WordP()->Get(1).AsAddress(); unsigned nArgs = 0; for (PolyWord p = args->WordP()->Get(2); !ML_Cons_Cell::IsNull(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t) nArgs++; // Allocate space for the cif followed by the argument type vector size_t space = sizeof(ffi_cif) + nArgs * sizeof(ffi_type*); ffi_cif *cif = (ffi_cif *)malloc(space); if (cif == 0) raise_syscall(taskData, "Insufficient memory", ENOMEM); ffi_type **atypes = (ffi_type **)(cif+1); // Copy the arguments types. ffi_type **at = atypes; for (PolyWord p = args->WordP()->Get(2); !ML_Cons_Cell::IsNull(p); p = ((ML_Cons_Cell*)p.AsObjPtr())->t) { PolyWord e = ((ML_Cons_Cell*)p.AsObjPtr())->h; *at++ = *(ffi_type**)(e.AsAddress()); } ffi_status status = ffi_prep_cif(cif, abi, nArgs, rtype, atypes); if (status == FFI_BAD_TYPEDEF) raise_exception_string(taskData, EXC_foreign, "Bad typedef in ffi_prep_cif"); else if (status == FFI_BAD_ABI) raise_exception_string(taskData, EXC_foreign, "Bad ABI in ffi_prep_cif"); else if (status != FFI_OK) raise_exception_string(taskData, EXC_foreign, "Error in ffi_prep_cif"); return toSysWord(taskData, cif); } case 56: // Call a function. { ffi_cif *cif = *(ffi_cif **)args->WordP()->Get(0).AsAddress(); void *f = *(void**)args->WordP()->Get(1).AsAddress(); void *res = *(void**)args->WordP()->Get(2).AsAddress(); void **arg = *(void***)args->WordP()->Get(3).AsAddress(); // We release the ML memory across the call so a GC can occur // even if this thread is blocked in the C code. processes->ThreadReleaseMLMemory(taskData); ffi_call(cif, FFI_FN(f), res, arg); processes->ThreadUseMLMemory(taskData); return taskData->saveVec.push(TAGGED(0)); } case 57: // Create a callback. { #ifdef INTERPRETED raise_exception_string(taskData, EXC_foreign, "Callbacks are not implemented in the byte code interpreter"); #endif Handle mlFunction = taskData->saveVec.push(args->WordP()->Get(0)); ffi_cif *cif = *(ffi_cif **)args->WordP()->Get(1).AsAddress(); void *resultFunction; // Allocate the memory. resultFunction is set to the executable address in or related to // the memory. ffi_closure *closure = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure), &resultFunction); if (closure == 0) raise_exception_string(taskData, EXC_foreign, "Callbacks not implemented or insufficient memory"); PLocker pLocker(&callbackTableLock); // Find a free entry in the table if there is one. unsigned entryNo = 0; while (entryNo < callBackEntries && callbackTable[entryNo].closureSpace != 0) entryNo++; if (entryNo == callBackEntries) { // Need to grow the table. struct _cbStructEntry *newTable = (struct _cbStructEntry*)realloc(callbackTable, (callBackEntries+1)*sizeof(struct _cbStructEntry)); if (newTable == 0) raise_exception_string(taskData, EXC_foreign, "Unable to allocate memory for callback table"); callbackTable = newTable; callBackEntries++; } callbackTable[entryNo].mlFunction = mlFunction->Word(); callbackTable[entryNo].closureSpace = closure; callbackTable[entryNo].resultFunction = resultFunction; if (ffi_prep_closure_loc(closure, cif, callbackEntryPt, (void*)((uintptr_t)entryNo), resultFunction) != FFI_OK) raise_exception_string(taskData, EXC_foreign,"libffi error: ffi_prep_closure_loc failed"); return toSysWord(taskData, resultFunction); } case 58: // Free an existing callback. { // The address returned from call 57 above is the executable address that can // be passed as a callback function. The writable memory address returned // as the result of ffi_closure_alloc may or may not be the same. To be safe // we need to search the table. void *resFun = *(void**)args->Word().AsAddress(); PLocker pLocker(&callbackTableLock); unsigned i = 0; while (i < callBackEntries) { if (callbackTable[i].resultFunction == resFun) { ffi_closure_free(callbackTable[i].closureSpace); callbackTable[i].closureSpace = 0; callbackTable[i].resultFunction = 0; callbackTable[i].mlFunction = TAGGED(0); // Release the ML function return taskData->saveVec.push(TAGGED(0)); } } raise_exception_string(taskData, EXC_foreign, "Invalid callback entry"); } default: { char msg[100]; sprintf(msg, "Unknown ffi function: %d", c); raise_exception_string(taskData, EXC_foreign, msg); return 0; } } }
void callback_free(struct callback* c) { ffi_closure_free(c->closure); sexp_release_object(c->ctx, c->proc); }