diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:45:23 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:45:27 +0900 |
commit | ee6939d73fd96606a92eee870014c58eafee5e63 (patch) | |
tree | 6a3526fab8e841879fbcab05749fcb4a91a4f580 /gi/pygi-argument.c | |
parent | 0df45a72dc2a72275a5c49c38b87f73341987192 (diff) | |
download | pygobject2-ee6939d73fd96606a92eee870014c58eafee5e63.tar.gz pygobject2-ee6939d73fd96606a92eee870014c58eafee5e63.tar.bz2 pygobject2-ee6939d73fd96606a92eee870014c58eafee5e63.zip |
Imported Upstream version 3.20.0
Change-Id: I8106882e9a0d7a8fb554f9549e7c2cde111c104b
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi/pygi-argument.c')
-rw-r--r-- | gi/pygi-argument.c | 1624 |
1 files changed, 334 insertions, 1290 deletions
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 894f60b..fdd461a 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -16,687 +16,269 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA + * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "pygi-private.h" +#include "pygobject-private.h" #include <string.h> #include <time.h> -#include <datetime.h> -#include <pygobject.h> #include <pyglib-python-compat.h> #include <pyglib.h> -static void -_pygi_g_type_tag_py_bounds (GITypeTag type_tag, - PyObject **lower, - PyObject **upper) +#include "pygi-value.h" +#include "pygi-basictype.h" +#include "pygi-object.h" +#include "pygi-struct-marshal.h" +#include "pygi-error.h" + +gboolean +pygi_argument_to_gssize (GIArgument *arg_in, + GITypeTag type_tag, + gssize *gssize_out) +{ + switch (type_tag) { + case GI_TYPE_TAG_INT8: + *gssize_out = arg_in->v_int8; + return TRUE; + case GI_TYPE_TAG_UINT8: + *gssize_out = arg_in->v_uint8; + return TRUE; + case GI_TYPE_TAG_INT16: + *gssize_out = arg_in->v_int16; + return TRUE; + case GI_TYPE_TAG_UINT16: + *gssize_out = arg_in->v_uint16; + return TRUE; + case GI_TYPE_TAG_INT32: + *gssize_out = arg_in->v_int32; + return TRUE; + case GI_TYPE_TAG_UINT32: + *gssize_out = arg_in->v_uint32; + return TRUE; + case GI_TYPE_TAG_INT64: + *gssize_out = arg_in->v_int64; + return TRUE; + case GI_TYPE_TAG_UINT64: + *gssize_out = arg_in->v_uint64; + return TRUE; + default: + PyErr_Format (PyExc_TypeError, + "Unable to marshal %s to gssize", + g_type_tag_to_string(type_tag)); + return FALSE; + } +} + +void +_pygi_hash_pointer_to_arg (GIArgument *arg, + GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: - *lower = PYGLIB_PyLong_FromLong (-128); - *upper = PYGLIB_PyLong_FromLong (127); - break; - case GI_TYPE_TAG_UINT8: - *upper = PYGLIB_PyLong_FromLong (255); - *lower = PYGLIB_PyLong_FromLong (0); + arg->v_int8 = GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_INT16: - *lower = PYGLIB_PyLong_FromLong (-32768); - *upper = PYGLIB_PyLong_FromLong (32767); - break; - case GI_TYPE_TAG_UINT16: - *upper = PYGLIB_PyLong_FromLong (65535); - *lower = PYGLIB_PyLong_FromLong (0); + arg->v_int16 = GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_INT32: - *lower = PYGLIB_PyLong_FromLong (G_MININT32); - *upper = PYGLIB_PyLong_FromLong (G_MAXINT32); + arg->v_int32 = GPOINTER_TO_INT (arg->v_pointer); break; - case GI_TYPE_TAG_UINT32: - /* Note: On 32-bit archs, this number doesn't fit in a long. */ - *upper = PyLong_FromLongLong (G_MAXUINT32); - *lower = PYGLIB_PyLong_FromLong (0); - break; - case GI_TYPE_TAG_INT64: - /* Note: On 32-bit archs, these numbers don't fit in a long. */ - *lower = PyLong_FromLongLong (G_MININT64); - *upper = PyLong_FromLongLong (G_MAXINT64); - break; - case GI_TYPE_TAG_UINT64: - *upper = PyLong_FromUnsignedLongLong (G_MAXUINT64); - *lower = PYGLIB_PyLong_FromLong (0); - break; - case GI_TYPE_TAG_FLOAT: - *upper = PyFloat_FromDouble (G_MAXFLOAT); - *lower = PyFloat_FromDouble (-G_MAXFLOAT); - break; - case GI_TYPE_TAG_DOUBLE: - *upper = PyFloat_FromDouble (G_MAXDOUBLE); - *lower = PyFloat_FromDouble (-G_MAXDOUBLE); - break; - default: - PyErr_SetString (PyExc_TypeError, "Non-numeric type tag"); - *lower = *upper = NULL; - return; - } -} - -gint -_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, - gboolean is_instance, - PyObject *object) -{ - gint retval; - - GType g_type; - PyObject *py_type; - gchar *type_name_expected = NULL; - GIInfoType interface_type; - - interface_type = g_base_info_get_type (info); - if ( (interface_type == GI_INFO_TYPE_STRUCT) && - (g_struct_info_is_foreign ( (GIStructInfo*) info))) { - /* TODO: Could we check is the correct foreign type? */ - return 1; - } - - g_type = g_registered_type_info_get_g_type (info); - if (g_type != G_TYPE_NONE) { - py_type = _pygi_type_get_from_g_type (g_type); - } else { - py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info); - } - - if (py_type == NULL) { - return 0; - } - - g_assert (PyType_Check (py_type)); - - if (is_instance) { - retval = PyObject_IsInstance (object, py_type); - if (!retval) { - type_name_expected = _pygi_g_base_info_get_fullname ( - (GIBaseInfo *) info); - } - } else { - if (!PyObject_Type (py_type)) { - type_name_expected = "type"; - retval = 0; - } else if (!PyType_IsSubtype ( (PyTypeObject *) object, - (PyTypeObject *) py_type)) { - type_name_expected = _pygi_g_base_info_get_fullname ( - (GIBaseInfo *) info); - retval = 0; - } else { - retval = 1; - } - } - - Py_DECREF (py_type); - - if (!retval) { - PyTypeObject *object_type; - - if (type_name_expected == NULL) { - return -1; - } - - object_type = (PyTypeObject *) PyObject_Type (object); - if (object_type == NULL) { - return -1; - } - - PyErr_Format (PyExc_TypeError, "Must be %s, not %s", - type_name_expected, object_type->tp_name); - - g_free (type_name_expected); - } - - return retval; -} - -gint -_pygi_g_type_interface_check_object (GIBaseInfo *info, - PyObject *object) -{ - gint retval = 1; - GIInfoType info_type; - - info_type = g_base_info_get_type (info); - switch (info_type) { - case GI_INFO_TYPE_CALLBACK: - if (!PyCallable_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be callable, not %s", - object->ob_type->tp_name); - retval = 0; - } + case GI_TYPE_TAG_UINT8: + arg->v_uint8 = GPOINTER_TO_UINT (arg->v_pointer); break; - case GI_INFO_TYPE_ENUM: - retval = 0; - if (PyNumber_Check (object)) { - PyObject *number = PYGLIB_PyNumber_Long (object); - if (number == NULL) - PyErr_Clear(); - else { - glong value = PYGLIB_PyLong_AsLong (number); - int i; - for (i = 0; i < g_enum_info_get_n_values (info); i++) { - GIValueInfo *value_info = g_enum_info_get_value (info, i); - glong enum_value = g_value_info_get_value (value_info); - g_base_info_unref (value_info); - if (value == enum_value) { - retval = 1; - break; - } - } - } - } - if (retval < 1) - retval = _pygi_g_registered_type_info_check_object ( - (GIRegisteredTypeInfo *) info, TRUE, object); + case GI_TYPE_TAG_UINT16: + arg->v_uint16 = GPOINTER_TO_UINT (arg->v_pointer); break; - case GI_INFO_TYPE_FLAGS: - if (PyNumber_Check (object)) { - /* Accept 0 as a valid flag value */ - PyObject *number = PYGLIB_PyNumber_Long (object); - if (number == NULL) - PyErr_Clear(); - else { - long value = PYGLIB_PyLong_AsLong (number); - if (value == 0) - break; - else if (value == -1) - PyErr_Clear(); - } - } - retval = _pygi_g_registered_type_info_check_object ( - (GIRegisteredTypeInfo *) info, TRUE, object); + case GI_TYPE_TAG_UINT32: + arg->v_uint32 = GPOINTER_TO_UINT (arg->v_pointer); break; - case GI_INFO_TYPE_STRUCT: - { - GType type; - - /* Handle special cases. */ - type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); - if (g_type_is_a (type, G_TYPE_CLOSURE)) { - if (!(PyCallable_Check (object) || - pyg_type_from_object_strict (object, FALSE) == G_TYPE_CLOSURE)) { - PyErr_Format (PyExc_TypeError, "Must be callable, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } else if (g_type_is_a (type, G_TYPE_VALUE)) { - /* we can't check g_values because we don't have - * enough context so just pass them through */ - break; - } - - /* Fallback. */ - } - case GI_INFO_TYPE_BOXED: - case GI_INFO_TYPE_INTERFACE: - case GI_INFO_TYPE_OBJECT: - retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object); + case GI_TYPE_TAG_GTYPE: + arg->v_size = GPOINTER_TO_SIZE (arg->v_pointer); break; - case GI_INFO_TYPE_UNION: - - - retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object); - - /* If not the same type then check to see if the object's type - * is the same as one of the union's members - */ - if (retval == 0) { - gint i; - gint n_fields; - - n_fields = g_union_info_get_n_fields ( (GIUnionInfo *) info); - - for (i = 0; i < n_fields; i++) { - gint member_retval; - GIFieldInfo *field_info; - GITypeInfo *field_type_info; - - field_info = - g_union_info_get_field ( (GIUnionInfo *) info, i); - field_type_info = g_field_info_get_type (field_info); - - member_retval = _pygi_g_type_info_check_object( - field_type_info, - object, - TRUE); - - g_base_info_unref ( ( GIBaseInfo *) field_type_info); - g_base_info_unref ( ( GIBaseInfo *) field_info); - - if (member_retval == 1) { - retval = member_retval; - break; - } - } - } - + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_INTERFACE: break; default: - g_assert_not_reached(); + g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag)); } - - return retval; } -gint -_pygi_g_type_info_check_object (GITypeInfo *type_info, - PyObject *object, - gboolean allow_none) +gpointer +_pygi_arg_to_hash_pointer (const GIArgument *arg, + GITypeTag type_tag) { - GITypeTag type_tag; - gint retval = 1; - - if (allow_none && object == Py_None) { - return retval; - } - - type_tag = g_type_info_get_tag (type_info); - switch (type_tag) { - case GI_TYPE_TAG_VOID: - /* No check; VOID means undefined type */ - break; - case GI_TYPE_TAG_BOOLEAN: - /* No check; every Python object has a truth value. */ - break; - case GI_TYPE_TAG_UINT8: - /* UINT8 types can be characters */ - if (PYGLIB_PyBytes_Check(object)) { - if (PYGLIB_PyBytes_Size(object) != 1) { - PyErr_Format (PyExc_TypeError, "Must be a single character"); - retval = 0; - break; - } - - break; - } case GI_TYPE_TAG_INT8: + return GINT_TO_POINTER (arg->v_int8); + case GI_TYPE_TAG_UINT8: + return GINT_TO_POINTER (arg->v_uint8); case GI_TYPE_TAG_INT16: + return GINT_TO_POINTER (arg->v_int16); case GI_TYPE_TAG_UINT16: + return GINT_TO_POINTER (arg->v_uint16); case GI_TYPE_TAG_INT32: + return GINT_TO_POINTER (arg->v_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: - { - PyObject *number, *lower, *upper; - - if (!PyNumber_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be number, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - if (type_tag == GI_TYPE_TAG_FLOAT || type_tag == GI_TYPE_TAG_DOUBLE) { - number = PyNumber_Float (object); - } else { - number = PYGLIB_PyNumber_Long (object); - } - - _pygi_g_type_tag_py_bounds (type_tag, &lower, &upper); - - if (lower == NULL || upper == NULL || number == NULL) { - retval = -1; - goto check_number_release; - } - - /* Check bounds */ - if (PyObject_RichCompareBool (lower, number, Py_GT) - || PyObject_RichCompareBool (upper, number, Py_LT)) { - PyObject *lower_str; - PyObject *upper_str; - - if (PyErr_Occurred()) { - retval = -1; - goto check_number_release; - } - - lower_str = PyObject_Str (lower); - upper_str = PyObject_Str (upper); - if (lower_str == NULL || upper_str == NULL) { - retval = -1; - goto check_number_error_release; - } - -#if PY_VERSION_HEX < 0x03000000 - PyErr_Format (PyExc_ValueError, "Must range from %s to %s", - PyString_AS_STRING (lower_str), - PyString_AS_STRING (upper_str)); -#else - { - PyObject *lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str); - if (!lower_pybytes_obj) - goto utf8_fail; - - PyObject *upper_pybytes_obj = PyUnicode_AsUTF8String (upper_str); - if (!upper_pybytes_obj) { - Py_DECREF(lower_pybytes_obj); - goto utf8_fail; - } - - PyErr_Format (PyExc_ValueError, "Must range from %s to %s", - PyBytes_AsString (lower_pybytes_obj), - PyBytes_AsString (upper_pybytes_obj)); - Py_DECREF (lower_pybytes_obj); - Py_DECREF (upper_pybytes_obj); - } -utf8_fail: -#endif - retval = 0; - -check_number_error_release: - Py_XDECREF (lower_str); - Py_XDECREF (upper_str); - } - -check_number_release: - Py_XDECREF (number); - Py_XDECREF (lower); - Py_XDECREF (upper); - break; - } + return GINT_TO_POINTER (arg->v_uint32); case GI_TYPE_TAG_GTYPE: - { - if (pyg_type_from_object (object) == 0) { - PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - } - case GI_TYPE_TAG_UNICHAR: - { - Py_ssize_t size; - if (PyUnicode_Check (object)) { - size = PyUnicode_GET_SIZE (object); -#if PY_VERSION_HEX < 0x03000000 - } else if (PyString_Check (object)) { - PyObject *pyuni = PyUnicode_FromEncodedObject (object, "UTF-8", "strict"); - size = PyUnicode_GET_SIZE (pyuni); - Py_DECREF(pyuni); -#endif - } else { - PyErr_Format (PyExc_TypeError, "Must be string, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - if (size != 1) { - PyErr_Format (PyExc_TypeError, "Must be a one character string, not %ld characters", - size); - retval = 0; - break; - } - - break; - } + return GSIZE_TO_POINTER (arg->v_size); case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: - if (!PYGLIB_PyBaseString_Check (object) ) { - PyErr_Format (PyExc_TypeError, "Must be string, not %s", - object->ob_type->tp_name); - retval = 0; - } - break; - case GI_TYPE_TAG_ARRAY: - { - gssize fixed_size; - Py_ssize_t length; - GITypeInfo *item_type_info; - Py_ssize_t i; - - if (!PySequence_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - length = PySequence_Length (object); - if (length < 0) { - retval = -1; - break; - } - - fixed_size = g_type_info_get_array_fixed_size (type_info); - if (fixed_size >= 0 && length != fixed_size) { - PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd", - fixed_size, length); - retval = 0; - break; - } - - item_type_info = g_type_info_get_param_type (type_info, 0); - g_assert (item_type_info != NULL); - - /* FIXME: This is insain. We really should only check the first - * object and perhaps have a debugging mode. Large arrays - * will cause apps to slow to a crawl. - */ - for (i = 0; i < length; i++) { - PyObject *item; - - item = PySequence_GetItem (object, i); - if (item == NULL) { - retval = -1; - break; - } - - retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE); - - Py_DECREF (item); - - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Item %zd: ", i); - break; - } - } - - g_base_info_unref ( (GIBaseInfo *) item_type_info); - - break; - } case GI_TYPE_TAG_INTERFACE: - { - GIBaseInfo *info; - - info = g_type_info_get_interface (type_info); - g_assert (info != NULL); - - retval = _pygi_g_type_interface_check_object(info, object); - - g_base_info_unref (info); - break; - } - case GI_TYPE_TAG_GLIST: - case GI_TYPE_TAG_GSLIST: - { - Py_ssize_t length; - GITypeInfo *item_type_info; - Py_ssize_t i; - - if (!PySequence_Check (object)) { - PyErr_Format (PyExc_TypeError, "Must be sequence, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - length = PySequence_Length (object); - if (length < 0) { - retval = -1; - break; - } - - item_type_info = g_type_info_get_param_type (type_info, 0); - g_assert (item_type_info != NULL); - - for (i = 0; i < length; i++) { - PyObject *item; - - item = PySequence_GetItem (object, i); - if (item == NULL) { - retval = -1; - break; - } - - retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE); - - Py_DECREF (item); - - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Item %zd: ", i); - break; - } - } - - g_base_info_unref ( (GIBaseInfo *) item_type_info); - break; - } - case GI_TYPE_TAG_GHASH: - { - Py_ssize_t length; - PyObject *keys; - PyObject *values; - GITypeInfo *key_type_info; - GITypeInfo *value_type_info; - Py_ssize_t i; - - keys = PyMapping_Keys (object); - if (keys == NULL) { - PyErr_Format (PyExc_TypeError, "Must be mapping, not %s", - object->ob_type->tp_name); - retval = 0; - break; - } - - length = PyMapping_Length (object); - if (length < 0) { - Py_DECREF (keys); - retval = -1; - break; - } - - values = PyMapping_Values (object); - if (values == NULL) { - retval = -1; - Py_DECREF (keys); - break; - } - - key_type_info = g_type_info_get_param_type (type_info, 0); - g_assert (key_type_info != NULL); - - value_type_info = g_type_info_get_param_type (type_info, 1); - g_assert (value_type_info != NULL); - - for (i = 0; i < length; i++) { - PyObject *key; - PyObject *value; - - key = PyList_GET_ITEM (keys, i); - value = PyList_GET_ITEM (values, i); - - retval = _pygi_g_type_info_check_object (key_type_info, key, TRUE); - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Key %zd :", i); - break; - } + return arg->v_pointer; + default: + g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag)); + return arg->v_pointer; + } +} - retval = _pygi_g_type_info_check_object (value_type_info, value, TRUE); - if (retval < 0) { - break; - } - if (!retval) { - _PyGI_ERROR_PREFIX ("Value %zd :", i); - break; - } - } - g_base_info_unref ( (GIBaseInfo *) key_type_info); - g_base_info_unref ( (GIBaseInfo *) value_type_info); - Py_DECREF (values); - Py_DECREF (keys); - break; - } - case GI_TYPE_TAG_ERROR: - PyErr_SetString (PyExc_NotImplementedError, "Error marshalling is not supported yet"); - /* TODO */ - break; +/** + * _pygi_argument_array_length_marshal: + * @length_arg_index: Index of length argument in the callables args list. + * @user_data1: (type Array(GValue)): Array of GValue arguments to retrieve length + * @user_data2: (type GICallableInfo): Callable info to get the argument from. + * + * Generic marshalling policy for array length arguments in callables. + * + * Returns: The length of the array or -1 on failure. + */ +gssize +_pygi_argument_array_length_marshal (gsize length_arg_index, + void *user_data1, + void *user_data2) +{ + GIArgInfo length_arg_info; + GITypeInfo length_type_info; + GIArgument length_arg; + gssize array_len = -1; + GValue *values = (GValue *)user_data1; + GICallableInfo *callable_info = (GICallableInfo *)user_data2; + + g_callable_info_load_arg (callable_info, length_arg_index, &length_arg_info); + g_arg_info_load_type (&length_arg_info, &length_type_info); + + length_arg = _pygi_argument_from_g_value (&(values[length_arg_index]), + &length_type_info); + if (!pygi_argument_to_gssize (&length_arg, + g_type_info_get_tag (&length_type_info), + &array_len)) { + return -1; } - return retval; + return array_len; } +/** + * _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, - GIArgument *args[], - GITypeInfo *type_info, - gboolean is_method) + 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); - 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); + item_size = _pygi_g_type_info_size (item_type_info); - g_base_info_unref ( (GIBaseInfo *) 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 (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_arg_pos = g_type_info_get_array_length (type_info); + g_assert (length_arg_pos >= 0); - /* FIXME: Take into account the type of the argument. */ - length = args[length_arg_pos]->v_int; - } - } + length = array_length_policy (length_arg_pos, user_data1, user_data2); + if (length < 0) { + return NULL; + } + } + } - g_assert (length >= 0); + g_assert (length >= 0); - g_array = g_array_new (is_zero_terminated, FALSE, item_size); + g_array = g_array_new (is_zero_terminated, FALSE, item_size); - g_array->data = arg->v_pointer; - g_array->len = length; + 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; } @@ -708,234 +290,18 @@ _pygi_argument_from_object (PyObject *object, { GIArgument arg; GITypeTag type_tag; + gpointer cleanup_data = NULL; memset(&arg, 0, sizeof(GIArgument)); type_tag = g_type_info_get_tag (type_info); - switch (type_tag) { - case GI_TYPE_TAG_VOID: - g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); - arg.v_pointer = object; - break; - case GI_TYPE_TAG_BOOLEAN: - { - arg.v_boolean = PyObject_IsTrue (object); - break; - } - case GI_TYPE_TAG_INT8: - case GI_TYPE_TAG_INT16: - case GI_TYPE_TAG_INT32: - { - PyObject *int_; - - int_ = PYGLIB_PyNumber_Long (object); - if (int_ == NULL) { - break; - } - - if (type_tag == GI_TYPE_TAG_INT32) - arg.v_int32 = PYGLIB_PyLong_AsLong (int_); - else if (type_tag == GI_TYPE_TAG_INT8) - arg.v_int8 = PYGLIB_PyLong_AsLong (int_); - else if (type_tag == GI_TYPE_TAG_INT16) - arg.v_int16 = PYGLIB_PyLong_AsLong (int_); - - Py_DECREF (int_); - - break; - } - case GI_TYPE_TAG_UINT8: - case GI_TYPE_TAG_UINT16: - case GI_TYPE_TAG_UINT32: - case GI_TYPE_TAG_UINT64: - { - PyObject *number; - guint64 value; - - number = PYGLIB_PyNumber_Long (object); - if (number == NULL) { - break; - } - -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check (number)) { - value = PyInt_AS_LONG (number); - } else -#endif - value = PyLong_AsUnsignedLongLong (number); - - if (type_tag == GI_TYPE_TAG_UINT32) - arg.v_uint32 = value; - else if (type_tag == GI_TYPE_TAG_UINT64) - arg.v_uint64 = value; - else if (type_tag == GI_TYPE_TAG_UINT8) - arg.v_uint8 = value; - else if (type_tag == GI_TYPE_TAG_UINT16) - arg.v_uint16 = value; - - Py_DECREF (number); - - break; - } - case GI_TYPE_TAG_INT64: - { - PyObject *number; - gint64 value; - - number = PYGLIB_PyNumber_Long (object); - if (number == NULL) { - break; - } - -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check (number)) { - value = PyInt_AS_LONG (number); - } else -#endif - value = PyLong_AsLongLong (number); - - arg.v_int64 = value; - - Py_DECREF (number); - - break; - } - case GI_TYPE_TAG_FLOAT: - { - PyObject *float_; - - float_ = PyNumber_Float (object); - if (float_ == NULL) { - break; - } - - arg.v_float = (float) PyFloat_AsDouble (float_); - Py_DECREF (float_); - - break; - } - case GI_TYPE_TAG_DOUBLE: - { - PyObject *float_; - - float_ = PyNumber_Float (object); - if (float_ == NULL) { - break; - } - - arg.v_double = PyFloat_AsDouble (float_); - Py_DECREF (float_); - - break; - } - case GI_TYPE_TAG_GTYPE: - { - arg.v_long = pyg_type_from_object (object); - - break; - } - case GI_TYPE_TAG_UNICHAR: - { - gchar *string; - - if (object == Py_None) { - arg.v_uint32 = 0; - break; - } - -#if PY_VERSION_HEX < 0x03000000 - if (PyUnicode_Check(object)) { - PyObject *pystr_obj = PyUnicode_AsUTF8String (object); - - if (!pystr_obj) - break; - - string = g_strdup(PyString_AsString (pystr_obj)); - Py_DECREF(pystr_obj); - } else { - string = g_strdup(PyString_AsString (object)); - } -#else - { - PyObject *pybytes_obj = PyUnicode_AsUTF8String (object); - if (!pybytes_obj) - break; - - string = g_strdup(PyBytes_AsString (pybytes_obj)); - Py_DECREF (pybytes_obj); - } -#endif - - arg.v_uint32 = g_utf8_get_char (string); - - break; - } - case GI_TYPE_TAG_UTF8: - { - gchar *string; - - if (object == Py_None) { - arg.v_string = NULL; - break; - } -#if PY_VERSION_HEX < 0x03000000 - if (PyUnicode_Check(object)) { - PyObject *pystr_obj = PyUnicode_AsUTF8String (object); - - if (!pystr_obj) - break; - - string = g_strdup(PyString_AsString (pystr_obj)); - Py_DECREF(pystr_obj); - } else { - string = g_strdup(PyString_AsString (object)); - } -#else - { - PyObject *pybytes_obj = PyUnicode_AsUTF8String (object); - if (!pybytes_obj) - break; - - string = g_strdup(PyBytes_AsString (pybytes_obj)); - Py_DECREF (pybytes_obj); - } -#endif - arg.v_string = string; - - break; - } - case GI_TYPE_TAG_FILENAME: - { - GError *error = NULL; - gchar *string; - -#if PY_VERSION_HEX < 0x03000000 - string = g_strdup(PyString_AsString (object)); -#else - { - PyObject *pybytes_obj = PyUnicode_AsUTF8String (object); - if (!pybytes_obj) - break; - - string = g_strdup(PyBytes_AsString (pybytes_obj)); - Py_DECREF (pybytes_obj); - } -#endif - - if (string == NULL) { - break; - } - - arg.v_string = g_filename_from_utf8 (string, -1, NULL, NULL, &error); - g_free(string); - - if (arg.v_string == NULL) { - PyErr_SetString (PyExc_Exception, error->message); - /* TODO: Convert the error to an exception. */ - } + /* Ignores cleanup data for now. */ + if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data) || + PyErr_Occurred()) { + return arg; + } - break; - } + switch (type_tag) { case GI_TYPE_TAG_ARRAY: { Py_ssize_t length; @@ -951,6 +317,16 @@ _pygi_argument_from_object (PyObject *object, break; } + /* Note, strings are sequences, but we cannot accept them here */ + if (!PySequence_Check (object) || +#if PY_VERSION_HEX < 0x03000000 + PyString_Check (object) || +#endif + PyUnicode_Check (object)) { + PyErr_SetString (PyExc_TypeError, "expected sequence"); + break; + } + length = PySequence_Length (object); if (length < 0) { break; @@ -959,7 +335,11 @@ _pygi_argument_from_object (PyObject *object, 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); + /* we handle arrays that are really strings specially, see below */ + if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8) + item_size = 1; + else + item_size = sizeof (GIArgument); array = g_array_sized_new (is_zero_terminated, FALSE, item_size, length); if (array == NULL) { @@ -1032,84 +412,33 @@ array_success: case GI_INFO_TYPE_STRUCT: case GI_INFO_TYPE_UNION: { - GType type; - - if (object == Py_None) { - arg.v_pointer = NULL; - break; - } - - type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); - - /* Handle special cases first. */ - if (g_type_is_a (type, G_TYPE_VALUE)) { - GValue *value; - GType object_type; - gint retval; - - object_type = pyg_type_from_object_strict ( (PyObject *) object->ob_type, FALSE); - if (object_type == G_TYPE_INVALID) { - PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType"); - break; - } - - g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); - - value = g_slice_new0 (GValue); - - /* if already a gvalue, copy, else marshal into gvalue */ - if (object_type == G_TYPE_VALUE) { - /* src GValue's lifecycle is handled by Python - * so we have to copy it into the destination's - * GValue which is freed during the cleanup of - * invoke. - */ - GValue *src = (GValue *)((PyGObject *) object)->obj; - g_value_init (value, G_VALUE_TYPE (src)); - g_value_copy(src, value); - } else { - g_value_init (value, object_type); - retval = pyg_value_from_pyobject (value, object); - if (retval < 0) { - g_slice_free (GValue, value); - PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed"); - break; - } - } - - arg.v_pointer = value; - } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { - GClosure *closure; - - if (pyg_type_from_object_strict (object, FALSE) == G_TYPE_CLOSURE) { - closure = (GClosure *)pyg_boxed_get (object, void); - } else { - closure = pyg_closure_new (object, NULL, NULL); - if (closure == NULL) { - PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed"); - break; - } - } - - arg.v_pointer = closure; - } else if (g_struct_info_is_foreign (info)) { - PyObject *result; - result = pygi_struct_foreign_convert_to_g_argument ( - object, info, transfer, &arg); - } else if (g_type_is_a (type, G_TYPE_BOXED)) { - arg.v_pointer = pyg_boxed_get (object, void); - if (transfer == GI_TRANSFER_EVERYTHING) { - arg.v_pointer = g_boxed_copy (type, arg.v_pointer); - } - } else if (g_type_is_a (type, G_TYPE_POINTER) || - g_type_is_a (type, G_TYPE_VARIANT) || - type == G_TYPE_NONE) { - g_warn_if_fail (g_type_is_a (type, G_TYPE_VARIANT) || !g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING); - arg.v_pointer = pyg_pointer_get (object, void); - } else { - PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name (type)); - } - + GType g_type; + PyObject *py_type; + gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) && + (g_struct_info_is_foreign ((GIStructInfo *) info)); + + g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); + py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info); + + /* Note for G_TYPE_VALUE g_type: + * This will currently leak the GValue that is allocated and + * stashed in arg.v_pointer. Out argument marshaling for caller + * allocated GValues already pass in memory for the GValue. + * Further re-factoring is needed to fix this leak. + * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405 + */ + pygi_arg_struct_from_py_marshal (object, + &arg, + NULL, /*arg_name*/ + info, /*interface_info*/ + g_type, + py_type, + transfer, + FALSE, /*copy_reference*/ + is_foreign, + g_type_info_is_pointer (type_info)); + + Py_DECREF (py_type); break; } case GI_INFO_TYPE_ENUM: @@ -1122,7 +451,7 @@ array_success: break; } - arg.v_long = PYGLIB_PyLong_AsLong (int_); + arg.v_int = PYGLIB_PyLong_AsLong (int_); Py_DECREF (int_); @@ -1130,17 +459,10 @@ array_success: } case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: - if (object == Py_None) { - arg.v_pointer = NULL; - break; - } - - arg.v_pointer = pygobject_get (object); - if (transfer == GI_TRANSFER_EVERYTHING) { - g_object_ref (arg.v_pointer); - } - + /* An error within this call will result in a NULL arg */ + pygi_arg_gobject_out_arg_from_py (object, &arg, transfer); break; + default: g_assert_not_reached(); } @@ -1295,7 +617,8 @@ list_item_error: goto hash_table_item_error; } - g_hash_table_insert (hash_table, key.v_pointer, value.v_pointer); + g_hash_table_insert (hash_table, key.v_pointer, + _pygi_arg_to_hash_pointer (&value, g_type_info_get_tag (value_type_info))); continue; hash_table_item_error: @@ -1321,11 +644,25 @@ hash_table_release: PyErr_SetString (PyExc_NotImplementedError, "error marshalling is not supported yet"); /* TODO */ break; + default: + g_assert_not_reached (); } return arg; } +/** + * _pygi_argument_to_object: + * @arg: The argument to convert to an object. + * @type_info: Type info for @arg + * @transfer: + * + * If the argument is of type array, it must be encoded in a GArray, by calling + * _pygi_argument_to_array(). This logic can not be folded into this method + * as determining array lengths may require access to method call arguments. + * + * Returns: A PyObject representing @arg + */ PyObject * _pygi_argument_to_object (GIArgument *arg, GITypeInfo *type_info, @@ -1335,202 +672,72 @@ _pygi_argument_to_object (GIArgument *arg, PyObject *object = NULL; type_tag = g_type_info_get_tag (type_info); + object = _pygi_marshal_to_py_basic_type (arg, type_tag, transfer); + if (object) + return object; + switch (type_tag) { case GI_TYPE_TAG_VOID: - if (g_type_info_is_pointer (type_info) && - (arg->v_pointer != NULL)) { - /* Raw Python objects are passed to void* args */ - g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); - object = arg->v_pointer; - } else - object = Py_None; - Py_XINCREF (object); - break; - case GI_TYPE_TAG_BOOLEAN: - { - object = PyBool_FromLong (arg->v_boolean); - break; - } - case GI_TYPE_TAG_INT8: - { - object = PYGLIB_PyLong_FromLong (arg->v_int8); - break; - } - case GI_TYPE_TAG_UINT8: - { - object = PYGLIB_PyLong_FromLong (arg->v_uint8); - break; - } - case GI_TYPE_TAG_INT16: - { - object = PYGLIB_PyLong_FromLong (arg->v_int16); - break; - } - case GI_TYPE_TAG_UINT16: - { - object = PYGLIB_PyLong_FromLong (arg->v_uint16); - break; - } - case GI_TYPE_TAG_INT32: - { - object = PYGLIB_PyLong_FromLong (arg->v_int32); - break; - } - case GI_TYPE_TAG_UINT32: - { - object = PyLong_FromLongLong (arg->v_uint32); - break; - } - case GI_TYPE_TAG_INT64: - { - object = PyLong_FromLongLong (arg->v_int64); - break; - } - case GI_TYPE_TAG_UINT64: - { - object = PyLong_FromUnsignedLongLong (arg->v_uint64); - break; - } - case GI_TYPE_TAG_FLOAT: - { - object = PyFloat_FromDouble (arg->v_float); - break; - } - case GI_TYPE_TAG_DOUBLE: { - object = PyFloat_FromDouble (arg->v_double); - break; - } - case GI_TYPE_TAG_GTYPE: - { - object = pyg_type_wrapper_new ( (GType) arg->v_long); - break; - } - case GI_TYPE_TAG_UNICHAR: - { - /* Preserve the bidirectional mapping between 0 and "" */ - if (arg->v_uint32 == 0) { - object = PYGLIB_PyUnicode_FromString (""); - } else if (g_unichar_validate (arg->v_uint32)) { - gchar utf8[6]; - gint bytes; - - bytes = g_unichar_to_utf8 (arg->v_uint32, utf8); - object = PYGLIB_PyUnicode_FromStringAndSize ((char*)utf8, bytes); - } else { - /* TODO: Convert the error to an exception. */ - PyErr_Format (PyExc_TypeError, - "Invalid unicode codepoint %" G_GUINT32_FORMAT, - arg->v_uint32); - object = Py_None; - Py_INCREF (object); - } - break; - } - case GI_TYPE_TAG_UTF8: - if (arg->v_string == NULL) { - object = Py_None; - Py_INCREF (object); - break; - } - - object = PYGLIB_PyUnicode_FromString (arg->v_string); - break; - case GI_TYPE_TAG_FILENAME: - { - GError *error = NULL; - gchar *string; - - if (arg->v_string == NULL) { - object = Py_None; - Py_INCREF (object); - break; - } - - string = g_filename_to_utf8 (arg->v_string, -1, NULL, NULL, &error); - if (string == NULL) { - PyErr_SetString (PyExc_Exception, error->message); - /* TODO: Convert the error to an exception. */ - break; + if (g_type_info_is_pointer (type_info)) { + g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); + object = PyLong_FromVoidPtr (arg->v_pointer); } - - object = PYGLIB_PyUnicode_FromString (string); - - g_free (string); - break; } case GI_TYPE_TAG_ARRAY: { + /* Arrays are assumed to be packed in a GArray */ GArray *array; GITypeInfo *item_type_info; GITypeTag item_type_tag; GITransfer item_transfer; gsize i, item_size; - array = arg->v_pointer; - + if (arg->v_pointer == NULL) + return PyList_New (0); + item_type_info = g_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_type_tag = g_type_info_get_tag (item_type_info); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + array = arg->v_pointer; + item_size = g_array_get_element_size (array); + + if (G_UNLIKELY (item_size > sizeof(GIArgument))) { + g_critical ("Stack overflow protection. " + "Can't copy array element into GIArgument."); + return PyList_New (0); + } if (item_type_tag == GI_TYPE_TAG_UINT8) { /* Return as a byte array */ - if (arg->v_pointer == NULL) { - object = PYGLIB_PyBytes_FromString (""); - break; - } - - object = PYGLIB_PyBytes_FromStringAndSize(array->data, array->len); - break; - + object = PYGLIB_PyBytes_FromStringAndSize (array->data, array->len); } else { - if (arg->v_pointer == NULL) { - object = PyList_New (0); - break; - } - object = PyList_New (array->len); if (object == NULL) { + g_critical ("Failure to allocate array for %u items", array->len); + g_base_info_unref ( (GIBaseInfo *) item_type_info); break; } - } - item_size = g_array_get_element_size (array); - - for (i = 0; i < array->len; i++) { - GIArgument item; - PyObject *py_item; - gboolean is_struct = FALSE; - - if (item_type_tag == GI_TYPE_TAG_INTERFACE) { - GIBaseInfo *iface_info = g_type_info_get_interface (item_type_info); - switch (g_base_info_get_type (iface_info)) { - case GI_INFO_TYPE_STRUCT: - case GI_INFO_TYPE_BOXED: - is_struct = TRUE; - default: - break; + for (i = 0; i < array->len; i++) { + GIArgument item = { 0 }; + PyObject *py_item; + + memcpy (&item, array->data + i * item_size, item_size); + + py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer); + if (py_item == NULL) { + Py_CLEAR (object); + _PyGI_ERROR_PREFIX ("Item %zu: ", i); + break; } - g_base_info_unref ( (GIBaseInfo *) iface_info); - } - - if (is_struct) { - item.v_pointer = &_g_array_index (array, GIArgument, i); - } else { - memcpy (&item, &_g_array_index (array, GIArgument, i), item_size); - } - py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer); - if (py_item == NULL) { - Py_CLEAR (object); - _PyGI_ERROR_PREFIX ("Item %zu: ", i); - break; + PyList_SET_ITEM (object, i, py_item); } - - PyList_SET_ITEM (object, i, py_item); } g_base_info_unref ( (GIBaseInfo *) item_type_info); @@ -1547,85 +754,33 @@ _pygi_argument_to_object (GIArgument *arg, switch (info_type) { case GI_INFO_TYPE_CALLBACK: { - /* There is no way we can support a callback return - * as we are never sure if the callback was set from C - * or Python. API that return callbacks are broken - * so we print a warning and send back a None - */ - - g_warning ("You are trying to use an API which returns a callback." - "Callback returns can not be supported. Returning None instead."); - object = Py_None; - Py_INCREF (object); - break; + g_assert_not_reached(); } case GI_INFO_TYPE_BOXED: case GI_INFO_TYPE_STRUCT: case GI_INFO_TYPE_UNION: { - GType type; - - if (arg->v_pointer == NULL) { - object = Py_None; - Py_INCREF (object); - break; - } - - type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); - if (g_type_is_a (type, G_TYPE_VALUE)) { - object = pyg_value_as_pyobject (arg->v_pointer, FALSE); - } else if (g_struct_info_is_foreign (info)) { - object = pygi_struct_foreign_convert_from_g_argument (info, arg->v_pointer); - } else if (g_type_is_a (type, G_TYPE_BOXED)) { - PyObject *py_type; + PyObject *py_type; + GType g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); + gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) && + (g_struct_info_is_foreign ((GIStructInfo *) info)); - py_type = _pygi_type_get_from_g_type (type); - if (py_type == NULL) - break; - - object = _pygi_boxed_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING); - - Py_DECREF (py_type); - } else if (g_type_is_a (type, G_TYPE_POINTER)) { - PyObject *py_type; - - py_type = _pygi_type_get_from_g_type (type); - - if (py_type == NULL || !PyType_IsSubtype ( (PyTypeObject *) type, &PyGIStruct_Type)) { - g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); - object = pyg_pointer_new (type, arg->v_pointer); - } else { - object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING); - } - - Py_XDECREF (py_type); - } else if (type == G_TYPE_VARIANT) { - PyObject *py_type; - - g_variant_ref_sink (arg->v_pointer); + /* Special case variant and none to force loading from py module. */ + if (g_type == G_TYPE_VARIANT || g_type == G_TYPE_NONE) { py_type = _pygi_type_import_by_gi_info (info); - object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer, - transfer == GI_TRANSFER_EVERYTHING); - } else if (type == G_TYPE_NONE) { - PyObject *py_type; - - py_type = _pygi_type_import_by_gi_info (info); - if (py_type == NULL) { - break; - } - - /* Only structs created in invoke can be safely marked - * GI_TRANSFER_EVERYTHING. Trust that invoke has - * filtered correctly - */ - object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer, - transfer == GI_TRANSFER_EVERYTHING); - - Py_DECREF (py_type); } else { - PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name (type)); + py_type = _pygi_type_get_from_g_type (g_type); } + object = pygi_arg_struct_to_py_marshal (arg, + info, /*interface_info*/ + g_type, + py_type, + transfer, + FALSE, /*is_allocated*/ + is_foreign); + + Py_XDECREF (py_type); break; } case GI_INFO_TYPE_ENUM: @@ -1644,43 +799,29 @@ _pygi_argument_to_object (GIArgument *arg, return NULL; py_args = PyTuple_New (1); - if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_long)) != 0) { + if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_int)) != 0) { Py_DECREF (py_args); Py_DECREF (py_type); return NULL; } - object = PyObject_CallFunction (py_type, "l", arg->v_long); + object = PyObject_CallFunction (py_type, "i", arg->v_int); Py_DECREF (py_args); Py_DECREF (py_type); } else if (info_type == GI_INFO_TYPE_ENUM) { - object = pyg_enum_from_gtype (type, arg->v_long); + object = pyg_enum_from_gtype (type, arg->v_int); } else { - object = pyg_flags_from_gtype (type, arg->v_long); + object = pyg_flags_from_gtype (type, arg->v_uint); } break; } case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: - if (arg->v_pointer == NULL) { - object = Py_None; - Py_INCREF (object); - break; - } - - /* since we will unref the object when the - * wrapper is destroyed and we don't want - * GTK removing the object while the - * wrapper is live, we take a gobject reference - * when one is not transfered to us - */ - if (transfer == GI_TRANSFER_NOTHING) - g_object_ref (G_OBJECT(arg->v_pointer)); + object = pygi_arg_gobject_to_py_called_from_c (arg, transfer); - object = pygobject_new (arg->v_pointer); break; default: g_assert_not_reached(); @@ -1771,6 +912,7 @@ _pygi_argument_to_object (GIArgument *arg, break; } + _pygi_hash_pointer_to_arg (&value, g_type_info_get_tag (value_type_info)); py_value = _pygi_argument_to_object (&value, value_type_info, item_transfer); if (py_value == NULL) { Py_DECREF (py_key); @@ -1797,12 +939,12 @@ _pygi_argument_to_object (GIArgument *arg, GError *error = (GError *) arg->v_pointer; if (error != NULL && transfer == GI_TRANSFER_NOTHING) { /* If we have not been transferred the ownership we must copy - * the error, because pyglib_error_check() is going to free it. + * the error, because pygi_error_check() is going to free it. */ error = g_error_copy (error); } - if (pyglib_error_check (&error)) { + if (pygi_error_check (&error)) { PyObject *err_type; PyObject *err_value; PyObject *err_trace; @@ -1815,107 +957,15 @@ _pygi_argument_to_object (GIArgument *arg, Py_INCREF (object); break; } - } - } - - return object; -} - - -GIArgument -_pygi_argument_from_g_value(const GValue *value, - GITypeInfo *type_info) -{ - GIArgument arg = { 0, }; - - GITypeTag type_tag = g_type_info_get_tag (type_info); - switch (type_tag) { - case GI_TYPE_TAG_BOOLEAN: - arg.v_boolean = g_value_get_boolean (value); - break; - case GI_TYPE_TAG_INT8: - case GI_TYPE_TAG_INT16: - case GI_TYPE_TAG_INT32: - case GI_TYPE_TAG_INT64: - arg.v_int = g_value_get_int (value); - break; - case GI_TYPE_TAG_UINT8: - case GI_TYPE_TAG_UINT16: - case GI_TYPE_TAG_UINT32: - case GI_TYPE_TAG_UINT64: - arg.v_uint = g_value_get_uint (value); - break; - case GI_TYPE_TAG_UNICHAR: - arg.v_uint32 = g_value_get_schar (value); - break; - case GI_TYPE_TAG_FLOAT: - arg.v_float = g_value_get_float (value); - break; - case GI_TYPE_TAG_DOUBLE: - arg.v_double = g_value_get_double (value); - break; - case GI_TYPE_TAG_GTYPE: - arg.v_long = g_value_get_gtype (value); - break; - case GI_TYPE_TAG_UTF8: - case GI_TYPE_TAG_FILENAME: - arg.v_string = g_value_dup_string (value); - break; - case GI_TYPE_TAG_GLIST: - case GI_TYPE_TAG_GSLIST: - arg.v_pointer = g_value_get_pointer (value); - break; - case GI_TYPE_TAG_ARRAY: - case GI_TYPE_TAG_GHASH: - arg.v_pointer = g_value_get_boxed (value); - 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); - - g_base_info_unref (info); - - switch (info_type) { - case GI_INFO_TYPE_FLAGS: - arg.v_long = g_value_get_flags (value); - break; - case GI_INFO_TYPE_ENUM: - arg.v_long = g_value_get_enum (value); - break; - case GI_INFO_TYPE_INTERFACE: - case GI_INFO_TYPE_OBJECT: - arg.v_pointer = g_value_get_object (value); - break; - case GI_INFO_TYPE_BOXED: - case GI_INFO_TYPE_STRUCT: - case GI_INFO_TYPE_UNION: - if (G_VALUE_HOLDS(value, G_TYPE_BOXED)) { - arg.v_pointer = g_value_get_boxed (value); - } else if (G_VALUE_HOLDS(value, G_TYPE_VARIANT)) { - arg.v_pointer = g_value_get_variant (value); - } else { - arg.v_pointer = g_value_get_pointer (value); - } - break; - default: - g_warning("Converting of type '%s' is not implemented", g_info_type_to_string(info_type)); - g_assert_not_reached(); - } break; } - case GI_TYPE_TAG_ERROR: - arg.v_pointer = g_value_get_boxed (value); - break; - case GI_TYPE_TAG_VOID: - g_critical("Converting of type '%s' is not implemented", g_type_tag_to_string(type_tag)); + default: + { g_assert_not_reached(); + } } - return arg; + return object; } void @@ -2035,7 +1085,8 @@ _pygi_argument_release (GIArgument *arg, if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) { g_closure_unref (arg->v_pointer); } - } else if (g_struct_info_is_foreign ( (GIStructInfo*) info)) { + } else if (info_type == GI_INFO_TYPE_STRUCT && + g_struct_info_is_foreign ((GIStructInfo*) info)) { if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) { pygi_struct_foreign_release (info, arg->v_pointer); } @@ -2183,10 +1234,3 @@ _pygi_argument_release (GIArgument *arg, } } -void -_pygi_argument_init (void) -{ - PyDateTime_IMPORT; - _pygobject_import(); -} - |