Exemplo n.º 1
0
static void
fill_metadata_callback(GPtrArray *args_metadata)
{
    guint i;

    for (i = 0; i < args_metadata->len; i++) {
        RBGIArgMetadata *metadata;
        GIArgInfo *arg_info;
        gint closure_index;
        gint destroy_index;

        metadata = g_ptr_array_index(args_metadata, i);

        arg_info = &(metadata->arg_info);
        closure_index = g_arg_info_get_closure(arg_info);
        if (closure_index != -1) {
            RBGIArgMetadata *closure_metadata;
            closure_metadata = g_ptr_array_index(args_metadata, closure_index);
            closure_metadata->closure_p = TRUE;
            metadata->closure_in_arg_index = closure_metadata->in_arg_index;
        }

        destroy_index = g_arg_info_get_destroy(arg_info);
        if (destroy_index != -1) {
            RBGIArgMetadata *destroy_metadata;
            destroy_metadata = g_ptr_array_index(args_metadata, destroy_index);
            destroy_metadata->destroy_p = TRUE;
            metadata->destroy_in_arg_index = destroy_metadata->in_arg_index;
        }
    }
}
static gpointer
sv_to_callback (GIArgInfo * arg_info,
                GITypeInfo * type_info,
                SV * sv,
                GPerlI11nInvocationInfo * invocation_info)
{
	GIBaseInfo *callback_interface_info;
	GPerlI11nPerlCallbackInfo *callback_info;
	GIScopeType scope;

	/* the destroy notify func is handled by _handle_automatic_arg */

	dwarn ("      Perl callback at %d (%s)\n",
	       invocation_info->current_pos,
	       g_base_info_get_name (arg_info));

	callback_interface_info = g_type_info_get_interface (type_info);
	callback_info = create_perl_callback_closure (callback_interface_info, sv);
	callback_info->data_pos = g_arg_info_get_closure (arg_info);
	callback_info->destroy_pos = g_arg_info_get_destroy (arg_info);
	callback_info->free_after_use = FALSE;
	g_base_info_unref (callback_interface_info);

	dwarn ("      Perl callback data at %d, destroy at %d\n",
	       callback_info->data_pos, callback_info->destroy_pos);

	scope = (!gperl_sv_is_defined (sv))
		? GI_SCOPE_TYPE_CALL
		: g_arg_info_get_scope (arg_info);
	switch (scope) {
	    case GI_SCOPE_TYPE_CALL:
		dwarn ("      Perl callback has scope 'call'\n");
		free_after_call (invocation_info,
		                 (GFunc) release_perl_callback, callback_info);
		break;
	    case GI_SCOPE_TYPE_NOTIFIED:
		dwarn ("      Perl callback has scope 'notified'\n");
		/* This case is already taken care of by the notify
		 * stuff above */
		break;
	    case GI_SCOPE_TYPE_ASYNC:
		dwarn ("      Perl callback has scope 'async'\n");
		/* FIXME: callback_info->free_after_use = TRUE; */
		break;
	    default:
		ccroak ("unhandled scope type %d encountered",
		       g_arg_info_get_scope (arg_info));
	}

	invocation_info->callback_infos =
		g_slist_prepend (invocation_info->callback_infos,
		                 callback_info);

	dwarn ("      returning Perl closure %p from info %p\n",
	       callback_info->closure, callback_info);
	return callback_info->closure;
}
Exemplo n.º 3
0
Arquivo: marshal.c Projeto: ntd/lgi
/* Marshalls given callable from Lua to C. */
static int
marshal_2c_callable (lua_State *L, GICallableInfo *ci, GIArgInfo *ai,
		     gpointer *callback, int narg, gboolean optional,
		     GICallableInfo *argci, void **args)
{
  int nret = 0;
  GIScopeType scope;
  gpointer user_data = NULL;
  gint nargs = 0;

  if (argci != NULL)
    nargs = g_callable_info_get_n_args (argci);

  /* Check 'nil' in optional case.  In this case, return NULL as
     callback. */
  if (lua_isnoneornil (L, narg))
    {
      if (optional)
	{
	  *callback = NULL;

	  /* Also set associated destroy handler to NULL, because some
	     callees tend to call it when left as garbage even when
	     main callback is NULL (gtk_menu_popup_for_device()
	     case). */
	  if (ai != NULL)
	    {
	      gint arg = g_arg_info_get_destroy (ai);
	      if (arg >= 0 && arg < nargs)
		((GIArgument *) args[arg])->v_pointer = NULL;
	    }
	  return 0;
	}
      else
	return luaL_argerror (L, narg, "nil is not allowed");
    }

  /* Check lightuserdata case; simply use that data if provided. */
  if (lua_islightuserdata (L, narg))
    {
      *callback = lua_touserdata (L, narg);
      return 0;
    }

  if (argci != NULL)
    {
      gint arg = g_arg_info_get_closure (ai);

      /* user_data block is already preallocated from function call. */
      g_assert (args != NULL);
      if (arg >= 0 && arg < nargs)
	{
	  user_data = ((GIArgument *) args[arg])->v_pointer;
	  arg = g_arg_info_get_destroy (ai);
	  if (arg >= 0 && arg < nargs)
	    ((GIArgument *) args[arg])->v_pointer = lgi_closure_destroy;
	}
    }

  scope = g_arg_info_get_scope (ai);
  if (user_data == NULL)
    {
      /* Closure without user_data block.  Create new data block,
	 setup destruction according to scope. */
      user_data = lgi_closure_allocate (L, 1);
      if (scope == GI_SCOPE_TYPE_CALL)
	{
	  *lgi_guard_create (L, lgi_closure_destroy) = user_data;
	  nret++;
	}
      else
	g_assert (scope == GI_SCOPE_TYPE_ASYNC);
    }

  /* Create the closure. */
  lgi_callable_create (L, ci, NULL);
  *callback = lgi_closure_create (L, user_data, narg,
				  scope == GI_SCOPE_TYPE_ASYNC);
  return nret;
}
Exemplo n.º 4
0
static gboolean
pygi_arg_callback_setup_from_info (PyGICallbackCache  *arg_cache,
                                   GITypeInfo         *type_info,
                                   GIArgInfo          *arg_info,   /* may be null */
                                   GITransfer          transfer,
                                   PyGIDirection       direction,
                                   GIInterfaceInfo    *iface_info,
                                   PyGICallableCache  *callable_cache)
{
    PyGIArgCache *cache = (PyGIArgCache *)arg_cache;
    gssize child_offset = 0;

    if (!pygi_arg_base_setup ((PyGIArgCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }

    if (callable_cache != NULL)
        child_offset = callable_cache->args_offset;

    ( (PyGIArgCache *)arg_cache)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

    arg_cache->user_data_index = g_arg_info_get_closure (arg_info);
    if (arg_cache->user_data_index != -1)
        arg_cache->user_data_index += child_offset;

    arg_cache->destroy_notify_index = g_arg_info_get_destroy (arg_info);
    if (arg_cache->destroy_notify_index != -1)
        arg_cache->destroy_notify_index += child_offset;

    if (arg_cache->user_data_index >= 0) {
        PyGIArgCache *user_data_arg_cache = pygi_arg_cache_alloc ();
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
        user_data_arg_cache->direction = direction;
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
        _pygi_callable_cache_set_arg (callable_cache, arg_cache->user_data_index,
                                      user_data_arg_cache);
    }

    if (arg_cache->destroy_notify_index >= 0) {
        PyGIArgCache *destroy_arg_cache = pygi_arg_cache_alloc ();
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
        destroy_arg_cache->direction = direction;
        _pygi_callable_cache_set_arg (callable_cache, arg_cache->destroy_notify_index,
                                      destroy_arg_cache);
    }

    arg_cache->scope = g_arg_info_get_scope (arg_info);
    g_base_info_ref( (GIBaseInfo *)iface_info);
    arg_cache->interface_info = iface_info;

    if (direction & PYGI_DIRECTION_FROM_PYTHON) {
        cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
        cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
    }

    if (direction & PYGI_DIRECTION_TO_PYTHON) {
        cache->to_py_marshaller = _pygi_marshal_to_py_interface_callback;
    }

    return TRUE;
}
Exemplo n.º 5
0
gboolean
_pygi_scan_for_callbacks (GIFunctionInfo *function_info,
                          gboolean       is_method,
                          guint8        *callback_index,
                          guint8        *user_data_index,
                          guint8        *destroy_notify_index)
{
    guint i, n_args;

    *callback_index = G_MAXUINT8;
    *user_data_index = G_MAXUINT8;
    *destroy_notify_index = G_MAXUINT8;

    n_args = g_callable_info_get_n_args ( (GICallableInfo *) function_info);
    for (i = 0; i < n_args; i++) {
        GIDirection direction;
        GIArgInfo *arg_info;
        GITypeInfo *type_info;
        guint8 destroy, closure;
        GITypeTag type_tag;

        arg_info = g_callable_info_get_arg ( (GICallableInfo*) function_info, i);
        type_info = g_arg_info_get_type (arg_info);
        type_tag = g_type_info_get_tag (type_info);

        if (type_tag == GI_TYPE_TAG_INTERFACE) {
            GIBaseInfo* interface_info;
            GIInfoType interface_type;

            interface_info = g_type_info_get_interface (type_info);
            interface_type = g_base_info_get_type (interface_info);
            if (interface_type == GI_INFO_TYPE_CALLBACK &&
                    ! (strcmp (g_base_info_get_namespace ( (GIBaseInfo*) interface_info), "GLib") == 0 &&
                       (strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "DestroyNotify") == 0 ||
                       (strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "FreeFunc") == 0)))) {
                if (*callback_index != G_MAXUINT8) {
                    PyErr_Format (PyExc_TypeError, "Function %s.%s has multiple callbacks, not supported",
                                  g_base_info_get_namespace ( (GIBaseInfo*) function_info),
                                  g_base_info_get_name ( (GIBaseInfo*) function_info));
                    g_base_info_unref (interface_info);
                    return FALSE;
                }
                *callback_index = i;
            }
            g_base_info_unref (interface_info);
        }
        destroy = g_arg_info_get_destroy (arg_info);
        
        closure = g_arg_info_get_closure (arg_info);
        direction = g_arg_info_get_direction (arg_info);

        if (destroy > 0 && destroy < n_args) {
            if (*destroy_notify_index != G_MAXUINT8) {
                PyErr_Format (PyExc_TypeError, "Function %s has multiple GDestroyNotify, not supported",
                              g_base_info_get_name ( (GIBaseInfo*) function_info));
                return FALSE;
            }
            *destroy_notify_index = destroy;
        }

        if (closure > 0 && closure < n_args) {
            if (*user_data_index != G_MAXUINT8) {
                PyErr_Format (PyExc_TypeError, "Function %s has multiple user_data arguments, not supported",
                              g_base_info_get_name ( (GIBaseInfo*) function_info));
                return FALSE;
            }
            *user_data_index = closure;
        }

        g_base_info_unref ( (GIBaseInfo*) arg_info);
        g_base_info_unref ( (GIBaseInfo*) type_info);
    }

    return TRUE;
}