示例#1
0
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;
}
示例#2
0
/*
 * 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);
}
示例#3
0
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;
}
示例#5
0
文件: Storage.c 项目: LeapYear/ghc
// 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);
}
示例#7
0
文件: Storage.c 项目: LeapYear/ghc
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
}
示例#8
0
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);
}
示例#9
0
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);
}
示例#10
0
文件: ffi.o.c 项目: hoobaa/mecl
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
	}
;
}
示例#11
0
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);
}
示例#12
0
文件: Function.c 项目: shafferj/ffi
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);
}
示例#13
0
文件: Function.c 项目: shafferj/ffi
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;
}
示例#14
0
文件: callback.c 项目: miho/jna
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);
}
示例#15
0
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);
}
示例#16
0
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;
}
示例#17
0
 FFIData::~FFIData() {
   free(arg_types);
   XFREE(cif.arg_types);
   if(closure) ffi_closure_free(closure);
 }
示例#18
0
FFIData::~FFIData() {
    if(args_info) XFREE(args_info);
    if(cif.arg_types) XFREE(cif.arg_types);
    if(closure) ffi_closure_free(closure);
}
示例#19
0
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);
}