예제 #1
0
static VALUE
array_to_ruby(gpointer array, GITypeInfo *type_info)
{
    VALUE rb_array;
    GIArrayType array_type;
    gint n_elements;

    array_type = g_type_info_get_array_type(type_info);
    n_elements = g_type_info_get_array_length(type_info);
    if (n_elements == -1) {
        rb_array = rb_ary_new();
    } else {
        rb_array = rb_ary_new2(n_elements);
    }
    switch (array_type) {
      case GI_ARRAY_TYPE_C:
        array_c_to_ruby(array, type_info, rb_array);
        break;
      case GI_ARRAY_TYPE_ARRAY:
        rb_raise(rb_eNotImpError, "TODO: GIArgument(array)[array] -> Ruby");
        break;
      case GI_ARRAY_TYPE_PTR_ARRAY:
        rb_raise(rb_eNotImpError, "TODO: GIArgument(array)[ptr-array] -> Ruby");
        break;
      case GI_ARRAY_TYPE_BYTE_ARRAY:
        rb_raise(rb_eNotImpError, "TODO: GIArgument(array)[byte-array] -> Ruby");
        break;
      default:
        g_assert_not_reached();
        break;
    }

    return rb_array;
}
예제 #2
0
static void
rb_gi_argument_from_ruby_array(GIArgument *argument, GITypeInfo *type_info,
                               VALUE rb_argument)
{
    GIArrayType array_type;
    GITypeInfo *element_type_info;

    array_type = g_type_info_get_array_type(type_info);
    element_type_info = g_type_info_get_param_type(type_info, 0);
    switch (array_type) {
      case GI_ARRAY_TYPE_C:
        rb_gi_argument_from_ruby_array_c(argument,
                                         type_info, element_type_info,
                                         rb_argument);
        break;
      case GI_ARRAY_TYPE_ARRAY:
      case GI_ARRAY_TYPE_PTR_ARRAY:
      case GI_ARRAY_TYPE_BYTE_ARRAY:
        /* TODO */
        break;
      default:
        g_assert_not_reached();
        break;
    }
    g_base_info_unref(element_type_info);
}
예제 #3
0
static void
rb_gi_in_argument_free_array(GIArgument *argument, GITypeInfo *type_info)
{
    GIArrayType array_type;

    array_type = g_type_info_get_array_type(type_info);
    switch (array_type) {
      case GI_ARRAY_TYPE_C:
        g_free(argument->v_pointer);
        break;
      case GI_ARRAY_TYPE_ARRAY:
      case GI_ARRAY_TYPE_PTR_ARRAY:
      case GI_ARRAY_TYPE_BYTE_ARRAY:
        break;
      default:
        g_assert_not_reached();
        break;
    }
}
예제 #4
0
파일: boxed.c 프로젝트: Katyunechka/gjs
static gboolean
type_can_be_allocated_directly(GITypeInfo *type_info)
{
    gboolean is_simple = TRUE;

    if (g_type_info_is_pointer(type_info)) {
        if (g_type_info_get_tag(type_info) == GI_TYPE_TAG_ARRAY &&
            g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_C) {
            GITypeInfo *param_info;

            param_info = g_type_info_get_param_type(type_info, 0);
            is_simple = type_can_be_allocated_directly(param_info);

            g_base_info_unref((GIBaseInfo*)param_info);
        } else {
            is_simple = FALSE;
        }
    } else {
        switch (g_type_info_get_tag(type_info)) {
        case GI_TYPE_TAG_BOOLEAN:
        case GI_TYPE_TAG_INT8:
        case GI_TYPE_TAG_UINT8:
        case GI_TYPE_TAG_INT16:
        case GI_TYPE_TAG_UINT16:
        case GI_TYPE_TAG_INT32:
        case GI_TYPE_TAG_UINT32:
        case GI_TYPE_TAG_INT64:
        case GI_TYPE_TAG_UINT64:
        case GI_TYPE_TAG_FLOAT:
        case GI_TYPE_TAG_DOUBLE:
        case GI_TYPE_TAG_UNICHAR:
            break;
        case GI_TYPE_TAG_VOID:
        case GI_TYPE_TAG_GTYPE:
        case GI_TYPE_TAG_ERROR:
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
        case GI_TYPE_TAG_ARRAY:
        case GI_TYPE_TAG_GLIST:
        case GI_TYPE_TAG_GSLIST:
        case GI_TYPE_TAG_GHASH:
            break;
        case GI_TYPE_TAG_INTERFACE:
            {
                GIBaseInfo *interface = g_type_info_get_interface(type_info);
                switch (g_base_info_get_type(interface)) {
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_STRUCT:
                    if (!struct_is_simple((GIStructInfo *)interface))
                        is_simple = FALSE;
                    break;
                case GI_INFO_TYPE_UNION:
                    /* FIXME: Need to implement */
                    is_simple = FALSE;
                    break;
                case GI_INFO_TYPE_ENUM:
                case GI_INFO_TYPE_FLAGS:
                    break;
                case GI_INFO_TYPE_OBJECT:
                case GI_INFO_TYPE_VFUNC:
                case GI_INFO_TYPE_CALLBACK:
                case GI_INFO_TYPE_INVALID:
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_FUNCTION:
                case GI_INFO_TYPE_CONSTANT:
                case GI_INFO_TYPE_VALUE:
                case GI_INFO_TYPE_SIGNAL:
                case GI_INFO_TYPE_PROPERTY:
                case GI_INFO_TYPE_FIELD:
                case GI_INFO_TYPE_ARG:
                case GI_INFO_TYPE_TYPE:
                case GI_INFO_TYPE_UNRESOLVED:
                    is_simple = FALSE;
                    break;
                case GI_INFO_TYPE_INVALID_0:
                    g_assert_not_reached();
                    break;
                }

                g_base_info_unref(interface);
                break;
            }
        }
    }
    return is_simple;
}
예제 #5
0
파일: marshal.c 프로젝트: ntd/lgi
/* Marshalls single value from Lua to GLib/C. */
int
lgi_marshal_2c (lua_State *L, GITypeInfo *ti, GIArgInfo *ai,
		GITransfer transfer, gpointer target, int narg,
		int parent, GICallableInfo *ci, void **args)
{
  int nret = 0;
  gboolean optional = (parent == LGI_PARENT_CALLER_ALLOC) ||
    (ai == NULL || (g_arg_info_is_optional (ai) ||
		       g_arg_info_may_be_null (ai)));
  GITypeTag tag = g_type_info_get_tag (ti);
  GIArgument *arg = target;

  /* Convert narg stack position to absolute one, because during
     marshalling some temporary items might be pushed to the stack,
     which would disrupt relative stack addressing of the value. */
  lgi_makeabs(L, narg);

  switch (tag)
    {
    case GI_TYPE_TAG_BOOLEAN:
      {
	gboolean result;
	result = lua_toboolean (L, narg) ? TRUE : FALSE;
	if (parent == LGI_PARENT_FORCE_POINTER)
	  arg->v_pointer = GINT_TO_POINTER (result);
	else if (parent == LGI_PARENT_IS_RETVAL)
	  {
	    ReturnUnion *ru = (ReturnUnion *) arg;
	    ru->s = result;
	  }
	else
	  arg->v_boolean = result;
	break;
      }

    case GI_TYPE_TAG_FLOAT:
    case GI_TYPE_TAG_DOUBLE:
      {
	/* Retrieve number from given position. */
	lua_Number num = (optional && lua_isnoneornil (L, narg))
	  ? 0 : luaL_checknumber (L, narg);

	/* Marshalling float/double into pointer target is not possible. */
	g_return_val_if_fail (parent != LGI_PARENT_FORCE_POINTER, 0);

	/* Store read value into chosen target. */
	if (tag == GI_TYPE_TAG_FLOAT)
	  arg->v_float = (float) num;
	else
	  arg->v_double = (double) num;
	break;
      }

    case GI_TYPE_TAG_UTF8:
    case GI_TYPE_TAG_FILENAME:
      {
	gchar *str = NULL;
	int type = lua_type (L, narg);
	if (type == LUA_TLIGHTUSERDATA)
	  str = lua_touserdata (L, narg);
	else if (!optional || (type != LUA_TNIL && type != LUA_TNONE))
	{
	  if (type == LUA_TUSERDATA)
	    str = (gchar *) lgi_udata_test (L, narg, LGI_BYTES_BUFFER);
	  if (str == NULL)
	    str = (gchar *) luaL_checkstring (L, narg);
	}

	if (tag == GI_TYPE_TAG_FILENAME)
	  {
	    /* Convert from UTF-8 to filename encoding. */
	    if (str)
	      {
		str = g_filename_from_utf8 (str, -1, NULL, NULL, NULL);
		if (transfer != GI_TRANSFER_EVERYTHING)
		  {
		    /* Create temporary object on the stack which will
		       destroy the allocated temporary filename. */
		    *lgi_guard_create (L, g_free) = (gpointer) str;
		    nret = 1;
		  }
	      }
	  }
	else if (transfer == GI_TRANSFER_EVERYTHING)
	  str = g_strdup (str);
	if (parent == LGI_PARENT_FORCE_POINTER)
	  arg->v_pointer = str;
	else
	  arg->v_string = str;
      }
      break;

    case GI_TYPE_TAG_INTERFACE:
      {
	GIBaseInfo *info = g_type_info_get_interface (ti);
	GIInfoType type = g_base_info_get_type (info);
	int info_guard;
	lgi_gi_info_new (L, info);
	info_guard = lua_gettop (L);
	switch (type)
	  {
	  case GI_INFO_TYPE_ENUM:
	  case GI_INFO_TYPE_FLAGS:
	    /* If the argument is not numeric, convert to number
	       first.  Use enum/flags 'constructor' to do this. */
	    if (lua_type (L, narg) != LUA_TNUMBER)
	      {
		lgi_type_get_repotype (L, G_TYPE_INVALID, info);
		lua_pushvalue (L, narg);
		lua_call (L, 1, 1);
		narg = -1;
	      }

	    /* Directly store underlying value. */
	    marshal_2c_int (L, g_enum_info_get_storage_type (info), arg, narg,
			    optional, parent);

	    /* Remove the temporary value, to keep stack balanced. */
	    if (narg == -1)
	      lua_pop (L, 1);
	    break;

	  case GI_INFO_TYPE_STRUCT:
	  case GI_INFO_TYPE_UNION:
	    {
	      /* Ideally the g_type_info_is_pointer() should be
		 sufficient here, but there is some
		 gobject-introspection quirk that some struct
		 arguments might not be marked as pointers
		 (e.g. g_variant_equals(), which has ctype of
		 gconstpointer, and thus logic in girparser.c which
		 sets is_pointer attribute fails).  Workaround it by
		 checking also argument type - structs as C function
		 arguments are always passed as pointers. */
	      gboolean by_value =
		parent != LGI_PARENT_FORCE_POINTER &&
		((!g_type_info_is_pointer (ti) && ai == NULL) ||
		 parent == LGI_PARENT_CALLER_ALLOC);

	      lgi_type_get_repotype (L, G_TYPE_INVALID, info);
	      lgi_record_2c (L, narg, target, by_value,
			     transfer != GI_TRANSFER_NOTHING, optional, FALSE);
	      break;
	    }

	  case GI_INFO_TYPE_OBJECT:
	  case GI_INFO_TYPE_INTERFACE:
	    {
	      arg->v_pointer =
		lgi_object_2c (L, narg,
			       g_registered_type_info_get_g_type (info),
			       optional, FALSE,
			       transfer != GI_TRANSFER_NOTHING);
	      break;
	    }

	  case GI_INFO_TYPE_CALLBACK:
	    nret = marshal_2c_callable (L, info, ai, &arg->v_pointer, narg,
					optional, ci, args);
	    break;

	  default:
	    g_assert_not_reached ();
	  }
	lua_remove (L, info_guard);
      }
      break;

    case GI_TYPE_TAG_ARRAY:
      {
	gssize size;
	GIArrayType atype = g_type_info_get_array_type (ti);
	nret = marshal_2c_array (L, ti, atype, &arg->v_pointer, &size,
				 narg, optional, transfer);

	/* Fill in array length argument, if it is specified. */
	if (atype == GI_ARRAY_TYPE_C)
	  array_get_or_set_length (ti, NULL, size, ci, args);
	break;
      }

    case GI_TYPE_TAG_GLIST:
    case GI_TYPE_TAG_GSLIST:
      nret = marshal_2c_list (L, ti, tag, &arg->v_pointer, narg, transfer);
      break;

    case GI_TYPE_TAG_GHASH:
      nret = marshal_2c_hash (L, ti, (GHashTable **) &arg->v_pointer, narg,
			      optional, transfer);
      break;

    case GI_TYPE_TAG_VOID:
      if (g_type_info_is_pointer (ti))
	{
	  /* Check and marshal according to real Lua type. */
	  if (lua_isnoneornil (L, narg))
	    /* nil -> NULL. */
	    arg->v_pointer = NULL;
	  if (lua_type (L, narg) == LUA_TSTRING)
	    /* Use string directly. */
	    arg->v_pointer = (gpointer) lua_tostring (L, narg);
	  else
	    {
	      int type = lua_type (L, narg);
	      if (type == LUA_TLIGHTUSERDATA)
		/* Generic pointer. */
		arg->v_pointer = lua_touserdata (L, narg);
	      else
		{
		  /* Check memory buffer. */
		  arg->v_pointer = lgi_udata_test (L, narg, LGI_BYTES_BUFFER);
		  if (!arg->v_pointer)
		    {
		      /* Check object. */
		      arg->v_pointer = lgi_object_2c (L, narg, G_TYPE_INVALID,
						      FALSE, TRUE, FALSE);
		      if (!arg->v_pointer)
			{
			  /* Check any kind of record. */
			  lua_pushnil (L);
			  lgi_record_2c (L, narg, &arg->v_pointer, FALSE,
					 FALSE, FALSE, TRUE);
			}
		    }
		}
	    }
	}
      break;

    default:
      marshal_2c_int (L, tag, arg, narg, optional, parent);
    }

  return nret;
}
예제 #6
0
파일: marshal.c 프로젝트: ntd/lgi
/* Container marshaller function. */
static int
marshal_container_marshaller (lua_State *L)
{
  GValue *value;
  GITypeInfo **ti;
  GITypeTag tag;
  GITransfer transfer;
  gpointer data;
  int nret = 0;
  gboolean get_mode = lua_isnone (L, 3);

  /* Get GValue to operate on. */
  lgi_type_get_repotype (L, G_TYPE_VALUE, NULL);
  lgi_record_2c (L, 1, &value, FALSE, FALSE, FALSE, FALSE);

  /* Get raw pointer from the value. */
  if (get_mode)
    {
      if (G_VALUE_TYPE (value) == G_TYPE_POINTER)
	data = g_value_get_pointer (value);
      else
	data = g_value_get_boxed (value);
    }

  /* Get info and transfer from upvalue. */
  ti = lua_touserdata (L, lua_upvalueindex (1));
  tag = g_type_info_get_tag (*ti);
  transfer = lua_tointeger (L, lua_upvalueindex (2));

  switch (tag)
    {
    case GI_TYPE_TAG_ARRAY:
      {
	GIArrayType atype = g_type_info_get_array_type (*ti);
	gssize size = -1;
	if (get_mode)
	  {
	    if (lua_type (L, 2) == LUA_TTABLE)
	      {
		lua_getfield (L, 2, "length");
		size = luaL_optinteger (L, -1, -1);
		lua_pop (L, 1);
	      }
	    marshal_2lua_array (L, *ti, GI_DIRECTION_OUT, atype, transfer,
				data, size, 0);
	  }
	else
	  {
	    nret = marshal_2c_array (L, *ti, atype, &data, &size, 3, FALSE,
				     transfer);
	    if (lua_type (L, 2) == LUA_TTABLE)
	      {
		lua_pushnumber (L, size);
		lua_setfield (L, 2, "length");
	      }
	  }
	break;
      }

    case GI_TYPE_TAG_GSLIST:
    case GI_TYPE_TAG_GLIST:
      if (get_mode)
	marshal_2lua_list (L, *ti, GI_DIRECTION_OUT, tag, transfer, data);
      else
	nret = marshal_2c_list (L, *ti, tag, &data, 3, transfer);
      break;

    case GI_TYPE_TAG_GHASH:
      if (get_mode)
	marshal_2lua_hash (L, *ti, GI_DIRECTION_OUT, transfer, data);
      else
	nret = marshal_2c_hash (L, *ti, (GHashTable **) &data, 3, FALSE,
				transfer);
      break;

    default:
      g_assert_not_reached ();
    }

  /* Store result pointer to the value. */
  if (!get_mode)
    {
      if (G_VALUE_TYPE (value) == G_TYPE_POINTER)
	g_value_set_pointer (value, data);
      else
	g_value_set_boxed (value, data);
    }

  /* If there are any temporary objects, try to store them into
     attrs.keepalive table, if it is present. */
  if (!lua_isnoneornil (L, 2))
    {
      lua_getfield (L, 2, "keepalive");
      if (!lua_isnil (L, -1))
	for (lua_insert (L, -nret - 1); nret > 0; nret--)
	  {
	    lua_pushnumber (L, lua_objlen (L, -nret - 1));
	    lua_insert (L, -2);
	    lua_settable (L, -nret - 3);
	    lua_pop (L, 1);
	  }
      else
	lua_pop (L, nret);
      lua_pop (L, 1);
    }
  else
    lua_pop (L, nret);

  return get_mode ? 1 : 0;
}
예제 #7
0
파일: marshal.c 프로젝트: ntd/lgi
/* Marshalls single value from GLib/C to Lua.  Returns 1 if something
   was pushed to the stack. */
void
lgi_marshal_2lua (lua_State *L, GITypeInfo *ti, GIArgInfo *ai, GIDirection dir,
		  GITransfer transfer, gpointer source, int parent,
		  GICallableInfo *ci, void **args)
{
  gboolean own = (transfer != GI_TRANSFER_NOTHING);
  GITypeTag tag = g_type_info_get_tag (ti);
  GIArgument *arg = source;

  /* Make sure that parent is absolute index so that it is fixed even
     when we add/remove from the stack. */
  lgi_makeabs (L, parent);

  switch (tag)
    {
    case GI_TYPE_TAG_VOID:
      if (g_type_info_is_pointer (ti))
	/* Marshal pointer to simple lightuserdata. */
	lua_pushlightuserdata (L, arg->v_pointer);
      else
	lua_pushnil (L);
      break;

    case GI_TYPE_TAG_BOOLEAN:
      if (parent == LGI_PARENT_IS_RETVAL)
	{
	  ReturnUnion *ru = (ReturnUnion *) arg;
	  ru->arg.v_boolean = ru->s;
	}
      lua_pushboolean (L, arg->v_boolean);
      break;

    case GI_TYPE_TAG_FLOAT:
    case GI_TYPE_TAG_DOUBLE:
      g_return_if_fail (parent != LGI_PARENT_FORCE_POINTER);
      lua_pushnumber (L, (tag == GI_TYPE_TAG_FLOAT)
		      ? arg->v_float : arg->v_double);
      break;

    case GI_TYPE_TAG_UTF8:
    case GI_TYPE_TAG_FILENAME:
      {
	gchar *str = (parent == LGI_PARENT_FORCE_POINTER)
	  ? arg->v_pointer : arg->v_string;
	if (tag == GI_TYPE_TAG_FILENAME && str != NULL)
	  {
	    gchar *utf8 = g_filename_to_utf8 (str, -1, NULL, NULL, NULL);
	    lua_pushstring (L, utf8);
	    g_free (utf8);
	  }
	else
	  lua_pushstring (L, str);
	if (transfer == GI_TRANSFER_EVERYTHING)
	  g_free (str);
	break;
      }

    case GI_TYPE_TAG_INTERFACE:
      {
	GIBaseInfo *info = g_type_info_get_interface (ti);
	GIInfoType type = g_base_info_get_type (info);
	int info_guard;
	lgi_gi_info_new (L, info);
	info_guard = lua_gettop (L);
	switch (type)
	  {
	  case GI_INFO_TYPE_ENUM:
	  case GI_INFO_TYPE_FLAGS:
	    /* Prepare repotable of enum/flags on the stack. */
	    lgi_type_get_repotype (L, G_TYPE_INVALID, info);

	    /* Unmarshal the numeric value. */
	    marshal_2lua_int (L, g_enum_info_get_storage_type (info),
			      arg, parent);

	    /* Get symbolic value from the table. */
	    lua_gettable (L, -2);

	    /* Remove the table from the stack. */
	    lua_remove (L, -2);
	    break;

	  case GI_INFO_TYPE_STRUCT:
	  case GI_INFO_TYPE_UNION:
	    {
	      gboolean by_ref = parent == LGI_PARENT_FORCE_POINTER ||
		g_type_info_is_pointer (ti);
	      if (parent < LGI_PARENT_CALLER_ALLOC && by_ref)
		parent = 0;
	      lgi_type_get_repotype (L, G_TYPE_INVALID, info);
	      lgi_record_2lua (L, by_ref ? arg->v_pointer : source,
			       own, parent);
	      break;
	    }

	  case GI_INFO_TYPE_OBJECT:
	  case GI_INFO_TYPE_INTERFACE:
	    /* Avoid sinking for input arguments, because it wreaks
	       havoc to input arguments of vfunc callbacks during
	       InitiallyUnowned construction phase. */
	    lgi_object_2lua (L, arg->v_pointer, own, dir == GI_DIRECTION_IN);
	    break;

	  case GI_INFO_TYPE_CALLBACK:
	    if (arg->v_pointer == NULL)
	      lua_pushnil (L);
	    else
	      {
		lgi_callable_create (L, info, arg->v_pointer);
		if (ai != NULL && args != NULL)
		  {
		    gint closure = g_arg_info_get_closure (ai);
		    if (closure >= 0)
		      {
			/* Store context associated with the callback
			   to the callback object. */
			GIArgument *arg = args[closure];
			lua_pushlightuserdata (L, arg->v_pointer);
			lua_setfield (L, -2, "user_data");
		      }
		  }
	      }
	    break;

	  default:
	    g_assert_not_reached ();
	  }
	lua_remove (L, info_guard);
      }
      break;

    case GI_TYPE_TAG_ARRAY:
      {
	GIArrayType atype = g_type_info_get_array_type (ti);
	gssize size = -1;
	array_get_or_set_length (ti, &size, 0, ci, args);
	marshal_2lua_array (L, ti, dir, atype, transfer, arg->v_pointer, size,
			    parent);
      }
      break;

    case GI_TYPE_TAG_GSLIST:
    case GI_TYPE_TAG_GLIST:
      marshal_2lua_list (L, ti, dir, tag, transfer, arg->v_pointer);
      break;

    case GI_TYPE_TAG_GHASH:
      marshal_2lua_hash (L, ti, dir, transfer, arg->v_pointer);
      break;

    case GI_TYPE_TAG_ERROR:
      marshal_2lua_error (L, transfer, arg->v_pointer);
      break;

    default:
      marshal_2lua_int (L, tag, arg, parent);
    }
}
예제 #8
0
파일: marshal.c 프로젝트: ntd/lgi
gboolean
lgi_marshal_2c_caller_alloc (lua_State *L, GITypeInfo *ti, GIArgument *val,
			     int pos)
{
  gboolean handled = FALSE;
  switch (g_type_info_get_tag (ti))
    {
    case GI_TYPE_TAG_INTERFACE:
      {
	GIBaseInfo *ii = g_type_info_get_interface (ti);
	GIInfoType type = g_base_info_get_type (ii);
	if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_UNION)
	  {
	    if (pos == 0)
	      {
		lgi_type_get_repotype (L, G_TYPE_INVALID, ii);
		val->v_pointer = lgi_record_new (L, 1, FALSE);
	      }
	    handled = TRUE;
	  }

	g_base_info_unref (ii);
	break;
      }

    case GI_TYPE_TAG_ARRAY:
      {
	if (g_type_info_get_array_type (ti) == GI_ARRAY_TYPE_C)
	  {
	    gpointer *array_guard;
	    if (pos == 0)
	      {
		gssize elt_size, size;

		/* Currently only fixed-size arrays are supported. */
		elt_size =
		  array_get_elt_size (g_type_info_get_param_type (ti, 0));
		size = g_type_info_get_array_fixed_size (ti);
		g_assert (size > 0);

		/* Allocate underlying array.  It is temporary,
		   existing only for the duration of the call. */
		array_guard =
		  lgi_guard_create (L, (GDestroyNotify) g_array_unref);
		*array_guard = g_array_sized_new (FALSE, FALSE, elt_size, size);
		g_array_set_size (*array_guard, size);
	      }
	    else
	      {
		/* Convert the allocated array into Lua table with
		   contents. We have to do it in-place. */

		/* Make sure that pos is absolute, so that stack
		   shuffling below does not change the element it
		   points to. */
		if (pos < 0)
		  pos += lua_gettop (L) + 1;

		/* Get GArray from the guard and unmarshal it as a
		   full GArray into Lua. */
		array_guard = lua_touserdata (L, pos);
		marshal_2lua_array (L, ti, GI_DIRECTION_OUT,
				    GI_ARRAY_TYPE_ARRAY,
				    GI_TRANSFER_EVERYTHING, *array_guard,
				    -1, pos);

		/* Deactivate old guard, everything was marshalled
		   into the newly created and marshalled table. */
		*array_guard = NULL;

		/* Switch old value with the new data. */
		lua_replace (L, pos);
	      }
	    handled = TRUE;
	  }

	break;
      }

    default:
      break;
    }

  return handled;
}
예제 #9
0
/**
 * _pygi_argument_to_array
 * @arg: The argument to convert
 * @array_length_policy: Closure for marshalling the array length argument when needed.
 * @user_data1: Generic user data passed to the array_length_policy.
 * @user_data2: Generic user data passed to the array_length_policy.
 * @type_info: The type info for @arg
 * @out_free_array: A return location for a gboolean that indicates whether
 *                  or not the wrapped GArray should be freed
 *
 * Make sure an array type argument is wrapped in a GArray.
 *
 * Note: This method can *not* be folded into _pygi_argument_to_object() because
 * arrays are special in the sense that they might require access to @args in
 * order to get the length.
 *
 * Returns: A GArray wrapping @arg. If @out_free_array has been set to TRUE then
 *          free the array with g_array_free() without freeing the data members.
 *          Otherwise don't free the array.
 */
GArray *
_pygi_argument_to_array (GIArgument  *arg,
                         PyGIArgArrayLengthPolicy array_length_policy,
                         void        *user_data1,
                         void        *user_data2,
                         GITypeInfo  *type_info,
                         gboolean    *out_free_array)
{
    GITypeInfo *item_type_info;
    gboolean is_zero_terminated;
    gsize item_size;
    gssize length;
    GArray *g_array;
    
    g_return_val_if_fail (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY, NULL);

    if (arg->v_pointer == NULL) {
        return NULL;
    }
    
    switch (g_type_info_get_array_type (type_info)) {
        case GI_ARRAY_TYPE_C:
            is_zero_terminated = g_type_info_is_zero_terminated (type_info);
            item_type_info = g_type_info_get_param_type (type_info, 0);

            item_size = _pygi_g_type_info_size (item_type_info);

            g_base_info_unref ( (GIBaseInfo *) item_type_info);

            if (is_zero_terminated) {
                length = g_strv_length (arg->v_pointer);
            } else {
                length = g_type_info_get_array_fixed_size (type_info);
                if (length < 0) {
                    gint length_arg_pos;

                    if (G_UNLIKELY (array_length_policy == NULL)) {
                        g_critical ("Unable to determine array length for %p",
                                    arg->v_pointer);
                        g_array = g_array_new (is_zero_terminated, FALSE, item_size);
                        *out_free_array = TRUE;
                        return g_array;
                    }

                    length_arg_pos = g_type_info_get_array_length (type_info);
                    g_assert (length_arg_pos >= 0);

                    length = array_length_policy (length_arg_pos, user_data1, user_data2);
                    if (length < 0) {
                        return NULL;
                    }
                }
            }

            g_assert (length >= 0);

            g_array = g_array_new (is_zero_terminated, FALSE, item_size);

            g_free (g_array->data);
            g_array->data = arg->v_pointer;
            g_array->len = length;
            *out_free_array = TRUE;
            break;
        case GI_ARRAY_TYPE_ARRAY:
        case GI_ARRAY_TYPE_BYTE_ARRAY:
            /* Note: GByteArray is really just a GArray */
            g_array = arg->v_pointer;
            *out_free_array = FALSE;
            break;
        case GI_ARRAY_TYPE_PTR_ARRAY:
        {
            GPtrArray *ptr_array = (GPtrArray*) arg->v_pointer;
            g_array = g_array_sized_new (FALSE, FALSE,
                                         sizeof(gpointer),
                                         ptr_array->len);
             g_array->data = (char*) ptr_array->pdata;
             g_array->len = ptr_array->len;
             *out_free_array = TRUE;
             break;
        }
        default:
            g_critical ("Unexpected array type %u",
                        g_type_info_get_array_type (type_info));
            g_array = NULL;
            break;
    }

    return g_array;
}
예제 #10
0
static PyObject *
_wrap_g_field_info_get_value (PyGIBaseInfo *self,
                              PyObject     *args)
{
    PyObject *instance;
    GIBaseInfo *container_info;
    GIInfoType container_info_type;
    gpointer pointer;
    GITypeInfo *field_type_info;
    GIArgument value;
    PyObject *py_value = NULL;

    memset(&value, 0, sizeof(GIArgument));

    if (!PyArg_ParseTuple (args, "O:FieldInfo.get_value", &instance)) {
        return NULL;
    }

    container_info = g_base_info_get_container (self->info);
    g_assert (container_info != NULL);

    /* Check the instance. */
    if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, TRUE, instance)) {
        _PyGI_ERROR_PREFIX ("argument 1: ");
        return NULL;
    }

    /* Get the pointer to the container. */
    container_info_type = g_base_info_get_type (container_info);
    switch (container_info_type) {
        case GI_INFO_TYPE_UNION:
        case GI_INFO_TYPE_STRUCT:
            pointer = pyg_boxed_get (instance, void);
            break;
        case GI_INFO_TYPE_OBJECT:
            pointer = pygobject_get (instance);
            break;
        default:
            /* Other types don't have fields. */
            g_assert_not_reached();
    }

    /* Get the field's value. */
    field_type_info = g_field_info_get_type ( (GIFieldInfo *) self->info);

    /* A few types are not handled by g_field_info_get_field, so do it here. */
    if (!g_type_info_is_pointer (field_type_info)
            && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) {
        GIBaseInfo *info;
        GIInfoType info_type;

        if (! (g_field_info_get_flags ( (GIFieldInfo *) self->info) & GI_FIELD_IS_READABLE)) {
            PyErr_SetString (PyExc_RuntimeError, "field is not readable");
            goto out;
        }

        info = g_type_info_get_interface (field_type_info);

        info_type = g_base_info_get_type (info);

        g_base_info_unref (info);

        switch (info_type) {
            case GI_INFO_TYPE_UNION:
                PyErr_SetString (PyExc_NotImplementedError, "getting an union is not supported yet");
                goto out;
            case GI_INFO_TYPE_STRUCT:
            {
                gsize offset;

                offset = g_field_info_get_offset ( (GIFieldInfo *) self->info);

                value.v_pointer = pointer + offset;

                goto argument_to_object;
            }
            default:
                /* Fallback. */
                break;
        }
    }

    if (!g_field_info_get_field ( (GIFieldInfo *) self->info, pointer, &value)) {
        PyErr_SetString (PyExc_RuntimeError, "unable to get the value");
        goto out;
    }

    if ( (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) &&
            (g_type_info_get_array_type (field_type_info) == GI_ARRAY_TYPE_C)) {
        value.v_pointer = _pygi_argument_to_array (&value, NULL,
                                                   field_type_info, FALSE);
    }

argument_to_object:
    py_value = _pygi_argument_to_object (&value, field_type_info, GI_TRANSFER_NOTHING);

    if ( (value.v_pointer != NULL) &&
            (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) &&
               (g_type_info_get_array_type (field_type_info) == GI_ARRAY_TYPE_C)) {
        g_array_free (value.v_pointer, FALSE);
    }

out:
    g_base_info_unref ( (GIBaseInfo *) field_type_info);

    return py_value;
}