示例#1
0
PyObject *
_pygi_marshal_to_py_interface_enum (PyGIInvokeState   *state,
                                    PyGICallableCache *callable_cache,
                                    PyGIArgCache      *arg_cache,
                                    GIArgument        *arg)
{
    PyObject *py_obj = NULL;
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
    GIBaseInfo *interface;
    long c_long;

    interface = g_type_info_get_interface (arg_cache->type_info);
    g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);

    if (!gi_argument_to_c_long(arg, &c_long,
                               g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
        return NULL;
    }

    if (iface_cache->g_type == G_TYPE_NONE) {
        py_obj = PyObject_CallFunction (iface_cache->py_type, "l", c_long);
    } else {
        py_obj = pyg_enum_from_gtype (iface_cache->g_type, c_long);
    }
    g_base_info_unref (interface);
    return py_obj;
}
示例#2
0
static PyObject *
_pygi_marshal_to_py_interface_flags (PyGIInvokeState   *state,
                                     PyGICallableCache *callable_cache,
                                     PyGIArgCache      *arg_cache,
                                     GIArgument        *arg,
                                     gpointer          *cleanup_data)
{
    PyObject *py_obj = NULL;
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
    GIBaseInfo *interface;
    long c_long;

    interface = g_type_info_get_interface (arg_cache->type_info);
    g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);

    if (!gi_argument_to_c_long(arg, &c_long,
                               g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
        g_base_info_unref (interface);
        return NULL;
    }

    g_base_info_unref (interface);
    if (iface_cache->g_type == G_TYPE_NONE) {
        /* An enum with a GType of None is an enum without GType */

        PyObject *py_type = pygi_type_import_by_gi_info (iface_cache->interface_info);
        PyObject *py_args = NULL;

        if (!py_type)
            return NULL;

        py_args = PyTuple_New (1);
        if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (c_long)) != 0) {
            Py_DECREF (py_args);
            Py_DECREF (py_type);
            return NULL;
        }

        py_obj = PyObject_CallFunction (py_type, "l", c_long);

        Py_DECREF (py_args);
        Py_DECREF (py_type);
    } else {
        py_obj = pyg_flags_from_gtype (iface_cache->g_type, (guint)c_long);
    }

    return py_obj;
}
示例#3
0
static gboolean
_pygi_marshal_from_py_interface_flags (PyGIInvokeState   *state,
                                       PyGICallableCache *callable_cache,
                                       PyGIArgCache      *arg_cache,
                                       PyObject          *py_arg,
                                       GIArgument        *arg,
                                       gpointer          *cleanup_data)
{
    PyObject *py_long;
    unsigned long c_ulong;
    gint is_instance;
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
    GIBaseInfo *interface;

    is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);

    py_long = PYGLIB_PyNumber_Long (py_arg);
    if (py_long == NULL) {
        PyErr_Clear ();
        goto err;
    }

    c_ulong = PYGLIB_PyLong_AsUnsignedLong (py_long);
    Py_DECREF (py_long);

    /* only 0 or argument of type Flag is allowed */
    if (!is_instance && c_ulong != 0)
        goto err;

    /* Write c_long into arg */
    interface = g_type_info_get_interface (arg_cache->type_info);
    g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
    if (!gi_argument_from_c_long(arg, c_ulong,
                                 g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
        g_base_info_unref (interface);
        return FALSE;
    }

    g_base_info_unref (interface);
    return TRUE;

err:
    PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
                  iface_cache->type_name, Py_TYPE (py_arg)->tp_name);
    return FALSE;

}
示例#4
0
gsize
_pygi_g_type_info_size (GITypeInfo *type_info)
{
    gsize size = 0;

    GITypeTag type_tag;

    type_tag = g_type_info_get_tag (type_info);
    switch (type_tag) {
        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_GTYPE:
        case GI_TYPE_TAG_UNICHAR:
            size = _pygi_g_type_tag_size (type_tag);
            g_assert (size > 0);
            break;
        case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *info;
            GIInfoType info_type;

            info = g_type_info_get_interface (type_info);
            info_type = g_base_info_get_type (info);

            switch (info_type) {
                case GI_INFO_TYPE_STRUCT:
                    if (g_type_info_is_pointer (type_info)) {
                        size = sizeof (gpointer);
                    } else {
                        size = g_struct_info_get_size ( (GIStructInfo *) info);
                    }
                    break;
                case GI_INFO_TYPE_UNION:
                    if (g_type_info_is_pointer (type_info)) {
                        size = sizeof (gpointer);
                    } else {
                        size = g_union_info_get_size ( (GIUnionInfo *) info);
                    }
                    break;
                case GI_INFO_TYPE_ENUM:
                case GI_INFO_TYPE_FLAGS:
                    if (g_type_info_is_pointer (type_info)) {
                        size = sizeof (gpointer);
                    } else {
                        GITypeTag type_tag;

                        type_tag = g_enum_info_get_storage_type ( (GIEnumInfo *) info);
                        size = _pygi_g_type_tag_size (type_tag);
                    }
                    break;
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_OBJECT:
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_CALLBACK:
                    size = sizeof (gpointer);
                    break;
                case GI_INFO_TYPE_VFUNC:
                case GI_INFO_TYPE_INVALID:
                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:
                default:
                    g_assert_not_reached();
                    break;
            }

            g_base_info_unref (info);
            break;
        }
        case GI_TYPE_TAG_ARRAY:
        case GI_TYPE_TAG_VOID:
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
        case GI_TYPE_TAG_GLIST:
        case GI_TYPE_TAG_GSLIST:
        case GI_TYPE_TAG_GHASH:
        case GI_TYPE_TAG_ERROR:
            size = sizeof (gpointer);
            break;
    }

    return size;
}
/**
 * g_field_info_set_field:
 * @field_info: a #GIFieldInfo
 * @mem: pointer to a block of memory representing a C structure or union
 * @value: a #GArgument holding the value to store
 *
 * Writes a field identified by a #GFieldInfo to a C structure or
 * union.  This only handles fields of simple C types. It will fail
 * for a field of a composite type like a nested structure or union
 * even if that is actually writable. Note also that that it will refuse
 * to write fields where memory management would by required. A field
 * with a type such as 'char *' must be set with a setter function.
 *
 * Returns: %TRUE if writing the field succeeded, otherwise %FALSE
 */
gboolean
g_field_info_set_field (GIFieldInfo     *field_info,
			gpointer         mem,
			const GArgument *value)
{
    int offset;
    GITypeInfo *type_info;
    gboolean result = FALSE;

    if ((g_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) == 0)
      return FALSE;

    offset = g_field_info_get_offset (field_info);
    type_info = g_field_info_get_type (field_info);

    if (!g_type_info_is_pointer (type_info))
      {
	switch (g_type_info_get_tag (type_info))
	  {
	  case GI_TYPE_TAG_VOID:
	    g_warning("Field %s: should not be have void type",
		      g_base_info_get_name ((GIBaseInfo *)field_info));
	    break;
	  case GI_TYPE_TAG_BOOLEAN:
	    G_STRUCT_MEMBER(gboolean, mem, offset) = value->v_boolean != FALSE;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT8:
	  case GI_TYPE_TAG_UINT8:
	    G_STRUCT_MEMBER(guint8, mem, offset) = value->v_uint8;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT16:
	  case GI_TYPE_TAG_UINT16:
	  case GI_TYPE_TAG_SHORT:
	  case GI_TYPE_TAG_USHORT:
	    G_STRUCT_MEMBER(guint16, mem, offset) = value->v_uint16;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT32:
	  case GI_TYPE_TAG_UINT32:
	  case GI_TYPE_TAG_INT:
	  case GI_TYPE_TAG_UINT:
	    G_STRUCT_MEMBER(guint32, mem, offset) = value->v_uint32;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT64:
	  case GI_TYPE_TAG_UINT64:
	    G_STRUCT_MEMBER(guint64, mem, offset) = value->v_uint64;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_LONG:
	  case GI_TYPE_TAG_ULONG:
	    G_STRUCT_MEMBER(gulong, mem, offset)= value->v_ulong;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_SSIZE:
	  case GI_TYPE_TAG_SIZE:
	  case GI_TYPE_TAG_GTYPE:
	    G_STRUCT_MEMBER(gsize, mem, offset) = value->v_size;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_FLOAT:
	    G_STRUCT_MEMBER(gfloat, mem, offset) = value->v_float;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_DOUBLE:
	    G_STRUCT_MEMBER(gdouble, mem, offset)= value->v_double;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_TIME_T:
#if SIZEOF_TIME_T == 4
            G_STRUCT_MEMBER(time_t, mem, offset) = value->v_int32;
#elif SIZEOF_TIME_T == 8
            G_STRUCT_MEMBER(time_t, mem, offset) = value->v_int64;
#else
#  error "Unexpected size for time_t: not 4 or 8"
#endif
	    result = TRUE;
	    break;
	  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:
	    g_warning("Field %s: type %s should have is_pointer set",
		      g_base_info_get_name ((GIBaseInfo *)field_info),
		      g_type_tag_to_string (g_type_info_get_tag (type_info)));
	    break;
	  case GI_TYPE_TAG_ERROR:
	    /* Needs to be handled by the language binding directly */
	    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_STRUCT:
		case GI_INFO_TYPE_UNION:
		case GI_INFO_TYPE_BOXED:
		  /* Needs to be handled by the language binding directly */
		  break;
		case GI_INFO_TYPE_OBJECT:
		  break;
		case GI_INFO_TYPE_ENUM:
		case GI_INFO_TYPE_FLAGS:
		  {
		    /* See FIXME above
		     */
		    GITypeTag storage_type = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
		    switch (storage_type)
		      {
		      case GI_TYPE_TAG_INT8:
		      case GI_TYPE_TAG_UINT8:
			G_STRUCT_MEMBER(guint8, mem, offset) = (guint8)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT16:
		      case GI_TYPE_TAG_UINT16:
		      case GI_TYPE_TAG_SHORT:
		      case GI_TYPE_TAG_USHORT:
			G_STRUCT_MEMBER(guint16, mem, offset) = (guint16)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT32:
		      case GI_TYPE_TAG_UINT32:
		      case GI_TYPE_TAG_INT:
		      case GI_TYPE_TAG_UINT:
			G_STRUCT_MEMBER(guint32, mem, offset) = (guint32)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT64:
		      case GI_TYPE_TAG_UINT64:
			G_STRUCT_MEMBER(guint64, mem, offset) = (guint64)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_LONG:
		      case GI_TYPE_TAG_ULONG:
			G_STRUCT_MEMBER(gulong, mem, offset) = (gulong)value->v_int;
			result = TRUE;
			break;
		      default:
			g_warning("Field %s: Unexpected enum storage type %s",
				  g_base_info_get_name ((GIBaseInfo *)field_info),
				  g_type_tag_to_string (storage_type));
			break;
		      }
		    break;
		  }
		  break;
		case GI_INFO_TYPE_VFUNC:
		case GI_INFO_TYPE_CALLBACK:
		  g_warning("Field%s: Interface type %d should have is_pointer set",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		case GI_INFO_TYPE_INVALID:
		case GI_INFO_TYPE_INTERFACE:
		case GI_INFO_TYPE_FUNCTION:
		case GI_INFO_TYPE_CONSTANT:
		case GI_INFO_TYPE_ERROR_DOMAIN:
		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:
		  g_warning("Field %s: Interface type %d not expected",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		}

	      g_base_info_unref ((GIBaseInfo *)interface);
	      break;
	    }
	    break;
	  }
      }

    g_base_info_unref ((GIBaseInfo *)type_info);

    return result;
}
/**
 * g_field_info_get_field:
 * @field_info: a #GIFieldInfo
 * @mem: pointer to a block of memory representing a C structure or union
 * @value: a #GArgument into which to store the value retrieved
 *
 * Reads a field identified by a #GFieldInfo from a C structure or
 * union.  This only handles fields of simple C types. It will fail
 * for a field of a composite type like a nested structure or union
 * even if that is actually readable.
 *
 * Returns: %TRUE if reading the field succeeded, otherwise %FALSE
 */
gboolean
g_field_info_get_field (GIFieldInfo *field_info,
			gpointer     mem,
			GArgument   *value)
{
    int offset;
    GITypeInfo *type_info;
    gboolean result = FALSE;

    if ((g_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) == 0)
      return FALSE;

    offset = g_field_info_get_offset (field_info);
    type_info = g_field_info_get_type (field_info);

    if (g_type_info_is_pointer (type_info))
      {
	value->v_pointer = G_STRUCT_MEMBER(gpointer, mem, offset);
	result = TRUE;
      }
    else
      {
	switch (g_type_info_get_tag (type_info))
	  {
	  case GI_TYPE_TAG_VOID:
	    g_warning("Field %s: should not be have void type",
		      g_base_info_get_name ((GIBaseInfo *)field_info));
	    break;
	  case GI_TYPE_TAG_BOOLEAN:
	    value->v_boolean = G_STRUCT_MEMBER(gboolean, mem, offset) != FALSE;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT8:
	  case GI_TYPE_TAG_UINT8:
	    value->v_uint8 = G_STRUCT_MEMBER(guint8, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT16:
	  case GI_TYPE_TAG_UINT16:
	  case GI_TYPE_TAG_SHORT:
	  case GI_TYPE_TAG_USHORT:
	    value->v_uint16 = G_STRUCT_MEMBER(guint16, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT32:
	  case GI_TYPE_TAG_UINT32:
	  case GI_TYPE_TAG_INT:
	  case GI_TYPE_TAG_UINT:
	    value->v_uint32 = G_STRUCT_MEMBER(guint32, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT64:
	  case GI_TYPE_TAG_UINT64:
	    value->v_uint64 = G_STRUCT_MEMBER(guint64, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_LONG:
	  case GI_TYPE_TAG_ULONG:
	    value->v_ulong = G_STRUCT_MEMBER(gulong, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_SSIZE:
	  case GI_TYPE_TAG_SIZE:
	  case GI_TYPE_TAG_GTYPE:
	    value->v_size = G_STRUCT_MEMBER(gsize, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_FLOAT:
	    value->v_float = G_STRUCT_MEMBER(gfloat, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_DOUBLE:
	    value->v_double = G_STRUCT_MEMBER(gdouble, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_TIME_T:
#if SIZEOF_TIME_T == 4
	    value->v_int32 = G_STRUCT_MEMBER(time_t, mem, offset);
#elif SIZEOF_TIME_T == 8
	    value->v_int64 = G_STRUCT_MEMBER(time_t, mem, offset);
#else
#  error "Unexpected size for time_t: not 4 or 8"
#endif
	    result = TRUE;
	    break;
	  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:
	    g_warning("Field %s: type %s should have is_pointer set",
		      g_base_info_get_name ((GIBaseInfo *)field_info),
		      g_type_tag_to_string (g_type_info_get_tag (type_info)));
	    break;
	  case GI_TYPE_TAG_ERROR:
	    /* Needs to be handled by the language binding directly */
	    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_STRUCT:
		case GI_INFO_TYPE_UNION:
		case GI_INFO_TYPE_BOXED:
		  /* Needs to be handled by the language binding directly */
		  break;
		case GI_INFO_TYPE_OBJECT:
		  break;
		case GI_INFO_TYPE_ENUM:
		case GI_INFO_TYPE_FLAGS:
		  {
		    /* FIXME: there's a mismatch here between the value->v_int we use
		     * here and the glong result returned from g_value_info_get_value().
		     * But to switch this to glong, we'd have to make g_function_info_invoke()
		     * translate value->v_long to the proper ABI for an enum function
		     * call parameter, which will usually be int, and then fix up language
		     * bindings.
		     */
		    GITypeTag storage_type = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
		    switch (storage_type)
		      {
		      case GI_TYPE_TAG_INT8:
		      case GI_TYPE_TAG_UINT8:
			value->v_int = (gint)G_STRUCT_MEMBER(guint8, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT16:
		      case GI_TYPE_TAG_UINT16:
		      case GI_TYPE_TAG_SHORT:
		      case GI_TYPE_TAG_USHORT:
			value->v_int = (gint)G_STRUCT_MEMBER(guint16, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT32:
		      case GI_TYPE_TAG_UINT32:
		      case GI_TYPE_TAG_INT:
		      case GI_TYPE_TAG_UINT:
			value->v_int = (gint)G_STRUCT_MEMBER(guint32, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT64:
		      case GI_TYPE_TAG_UINT64:
			value->v_int = (gint)G_STRUCT_MEMBER(guint64, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_LONG:
		      case GI_TYPE_TAG_ULONG:
			value->v_int = (gint)G_STRUCT_MEMBER(gulong, mem, offset);
			result = TRUE;
			break;
		      default:
			g_warning("Field %s: Unexpected enum storage type %s",
				  g_base_info_get_name ((GIBaseInfo *)field_info),
				  g_type_tag_to_string (storage_type));
			break;
		      }
		    break;
		  }
		case GI_INFO_TYPE_VFUNC:
		case GI_INFO_TYPE_CALLBACK:
		  g_warning("Field %s: Interface type %d should have is_pointer set",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		case GI_INFO_TYPE_INVALID:
		case GI_INFO_TYPE_INTERFACE:
		case GI_INFO_TYPE_FUNCTION:
		case GI_INFO_TYPE_CONSTANT:
		case GI_INFO_TYPE_ERROR_DOMAIN:
		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:
		  g_warning("Field %s: Interface type %d not expected",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		}

	      g_base_info_unref ((GIBaseInfo *)interface);
	      break;
	    }
	    break;
	  }
      }

    g_base_info_unref ((GIBaseInfo *)type_info);

    return result;
}
示例#7
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;
}
示例#8
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);
    }
}
示例#9
0
static gboolean
_pygi_marshal_from_py_interface_enum (PyGIInvokeState   *state,
                                      PyGICallableCache *callable_cache,
                                      PyGIArgCache      *arg_cache,
                                      PyObject          *py_arg,
                                      GIArgument        *arg,
                                      gpointer          *cleanup_data)
{
    PyObject *py_long;
    long c_long;
    gint is_instance;
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
    GIBaseInfo *interface = NULL;

    is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);

    py_long = PYGLIB_PyNumber_Long (py_arg);
    if (py_long == NULL) {
        PyErr_Clear();
        goto err;
    }

    c_long = PYGLIB_PyLong_AsLong (py_long);
    Py_DECREF (py_long);

    /* Write c_long into arg */
    interface = g_type_info_get_interface (arg_cache->type_info);
    assert(g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
    if (!gi_argument_from_c_long(arg,
                                 c_long,
                                 g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
          g_assert_not_reached();
          g_base_info_unref (interface);
          return FALSE;
    }

    /* If this is not an instance of the Enum type that we want
     * we need to check if the value is equivilant to one of the
     * Enum's memebers */
    if (!is_instance) {
        int i;
        gboolean is_found = FALSE;

        for (i = 0; i < g_enum_info_get_n_values (iface_cache->interface_info); i++) {
            GIValueInfo *value_info =
                g_enum_info_get_value (iface_cache->interface_info, i);
            gint64 enum_value = g_value_info_get_value (value_info);
            g_base_info_unref ( (GIBaseInfo *)value_info);
            if (c_long == enum_value) {
                is_found = TRUE;
                break;
            }
        }

        if (!is_found)
            goto err;
    }

    g_base_info_unref (interface);
    return TRUE;

err:
    if (interface)
        g_base_info_unref (interface);
    PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
                  iface_cache->type_name, Py_TYPE (py_arg)->tp_name);
    return FALSE;
}