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; }
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; }
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; }
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; }
/* 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; }
/* 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); } }
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; }