summaryrefslogtreecommitdiff
path: root/gi/pygi-argument.c
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:45:23 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:45:27 +0900
commitee6939d73fd96606a92eee870014c58eafee5e63 (patch)
tree6a3526fab8e841879fbcab05749fcb4a91a4f580 /gi/pygi-argument.c
parent0df45a72dc2a72275a5c49c38b87f73341987192 (diff)
downloadpygobject2-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.c1624
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();
-}
-