[pygobject/invoke-rewrite] [gi] implement out arg handling



commit 3b0eff80d2ee35e0417476f0a170b9e178e3d1ee
Author: John (J5) Palmieri <johnp redhat com>
Date:   Tue Jan 11 17:20:43 2011 -0500

    [gi] implement out arg handling

 gi/pygi-argument.c            |   43 +++++++++--------------------------
 gi/pygi-cache.c               |   22 ++++++++++++++----
 gi/pygi-invoke-state-struct.h |   13 ++++++++++
 gi/pygi-invoke.c              |   50 +++++++++++++++++++++++++++++++++++++++-
 4 files changed, 89 insertions(+), 39 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index fda7b1e..a490878 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -2856,10 +2856,7 @@ _pygi_marshal_out_int8 (PyGIInvokeState   *state,
                         PyGIArgCache      *arg_cache,
                         GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
-
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
+    PyObject *py_obj = PYGLIB_PyLong_FromLong(arg->v_int8);
     return py_obj;
 }
 
@@ -2869,10 +2866,8 @@ _pygi_marshal_out_uint8 (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj =  PYGLIB_PyLong_FromLong(arg->v_uint8);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2882,10 +2877,8 @@ _pygi_marshal_out_int16 (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj =  PYGLIB_PyLong_FromLong(arg->v_int16);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2895,10 +2888,8 @@ _pygi_marshal_out_uint16 (PyGIInvokeState   *state,
                           PyGIArgCache      *arg_cache,
                           GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj =  PYGLIB_PyLong_FromLong(arg->v_uint16);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2908,10 +2899,8 @@ _pygi_marshal_out_int32 (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj = PYGLIB_PyLong_FromLong(arg->v_int32);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2921,10 +2910,8 @@ _pygi_marshal_out_uint32 (PyGIInvokeState   *state,
                           PyGIArgCache      *arg_cache,
                           GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj = PyLong_FromLongLong(arg->v_uint32);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2934,10 +2921,8 @@ _pygi_marshal_out_int64 (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj = PyLong_FromLongLong(arg->v_int64);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2947,10 +2932,8 @@ _pygi_marshal_out_uint64 (PyGIInvokeState   *state,
                           PyGIArgCache      *arg_cache,
                           GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj = PyLong_FromUnsignedLongLong(arg->v_uint64);
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
@@ -2960,10 +2943,8 @@ _pygi_marshal_out_float (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
-
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
+    PyObject *py_obj = PyFloat_FromDouble (arg->v_float);
+ 
     return py_obj;
 }
 
@@ -2973,10 +2954,8 @@ _pygi_marshal_out_double (PyGIInvokeState   *state,
                           PyGIArgCache      *arg_cache,
                           GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
+    PyObject *py_obj = PyFloat_FromDouble (arg->v_double); 
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
     return py_obj;
 }
 
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 07ef9d1..168d946 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -914,6 +914,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
                      PyGIFunctionCache *function_cache)
 {
     int arg_index = 0;
+    int i;
     GITypeInfo *return_info;
     GITypeTag return_type_tag;
     PyGIArgCache *return_cache;
@@ -961,7 +962,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
     }
 
 
-    for (; arg_index < function_cache->n_args; arg_index++) {
+    for (i=0; arg_index < function_cache->n_args; arg_index++, i++) {
         PyGIArgCache *arg_cache = NULL;
         GIArgInfo *arg_info;
         GITypeInfo *type_info;
@@ -975,7 +976,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
             continue;
 
         arg_info =
-            g_callable_info_get_arg( (GICallableInfo *) function_info, arg_index);
+            g_callable_info_get_arg( (GICallableInfo *) function_info, i);
 
         direction = g_arg_info_get_direction(arg_info);
         transfer = g_arg_info_get_ownership_transfer(arg_info);
@@ -1005,10 +1006,21 @@ _args_cache_generate(GIFunctionInfo *function_info,
 
             case GI_DIRECTION_OUT:
                 function_cache->n_out_args++;
-                PyErr_Format(PyExc_NotImplementedError,
-                             "Out caching is not fully implemented yet");
+                arg_cache = 
+                    _arg_cache_out_new_from_type_info(return_info,
+                                                      function_cache,
+                                                      type_tag,
+                                                      transfer,
+                                                      direction,
+                                                      arg_index);
 
-                goto arg_err;
+                if (arg_cache == NULL)
+                    goto arg_err;
+
+                function_cache->out_args =
+                    g_slist_append(function_cache->out_args, arg_cache);
+
+                break;
 
             case GI_DIRECTION_INOUT:
                 PyErr_Format(PyExc_NotImplementedError,
diff --git a/gi/pygi-invoke-state-struct.h b/gi/pygi-invoke-state-struct.h
index 1c9bf3e..22ac8ea 100644
--- a/gi/pygi-invoke-state-struct.h
+++ b/gi/pygi-invoke-state-struct.h
@@ -14,7 +14,20 @@ typedef struct _PyGIInvokeState
 
     GIArgument **args;
     GIArgument *in_args;
+
+    /* Out args and out values
+     * In order to pass a parameter and get something back out in C
+     * we need to pass a pointer to the value, e.g.
+     *    int *out_integer;
+     *
+     * so while out_args == out_integer, out_value == *out_integer
+     * or in other words out_args = &out_values
+     *
+     * We do all of our processing on out_values but we pass out_args to 
+     * the actual function.
+     */
     GIArgument *out_args;
+    GIArgument *out_values;
 
     GIArgument return_arg;
 
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 23f7fa6..1be824c 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -929,6 +929,12 @@ _invoke_state_init_from_function_cache(PyGIInvokeState *state,
         return FALSE;
     }
 
+    state->out_values = g_slice_alloc0(cache->n_out_args * sizeof(GIArgument));
+    if (state->out_values == NULL && cache->n_out_args != 0) {
+        PyErr_NoMemory();
+        return FALSE;
+    }
+
     state->out_args = g_slice_alloc0(cache->n_out_args * sizeof(GIArgument));
     if (state->out_args == NULL && cache->n_out_args != 0) {
         PyErr_NoMemory();
@@ -946,6 +952,7 @@ _invoke_state_clear(PyGIInvokeState *state, PyGIFunctionCache *cache)
     g_slice_free1(cache->n_args * sizeof(GIArgument *), state->args);
     g_slice_free1(cache->n_in_args * sizeof(GIArgument), state->in_args);
     g_slice_free1(cache->n_out_args * sizeof(GIArgument), state->out_args);
+    g_slice_free1(cache->n_out_args * sizeof(GIArgument), state->out_values);
 }
 
 static inline gboolean
@@ -971,7 +978,8 @@ _invoke_marshal_in_args(PyGIInvokeState *state, PyGIFunctionCache *cache)
                 in_count++;
                 break;
             case GI_DIRECTION_OUT:
-                state->args[i] = &(state->out_args[out_count]);
+                state->out_args[out_count].v_pointer = &state->out_values[out_count];
+                state->args[i] = &state->out_values[out_count];
                 out_count++;
                 break;
         }
@@ -997,13 +1005,51 @@ _invoke_marshal_out_args(PyGIInvokeState *state, PyGIFunctionCache *cache)
 {
     PyObject *py_out = NULL;
     PyObject *py_return = NULL;
+    int total_out_args = cache->n_out_args;
+    gboolean has_return = FALSE;
 
     if (cache->return_cache)
         py_return = cache->return_cache->out_marshaller(state,
                                                         cache,
                                                         cache->return_cache,
                                                         &state->return_arg);
-    return py_return;
+
+    if (cache->return_cache->type_tag != GI_TYPE_TAG_VOID) {
+        total_out_args++;
+        has_return = TRUE;
+    }
+
+    if (cache->n_out_args == 0) {
+        py_out = py_return;
+    } else if (total_out_args == 1) {
+        /* if we get here there is one out arg an no return */
+        PyGIArgCache *arg_cache = (PyGIArgCache *)cache->out_args->data;
+        py_out = arg_cache->out_marshaller(state,
+                                           cache,
+                                           arg_cache,
+                                           &(state->out_values[0]));
+    } else {
+        int arg_index = 0;
+        GSList *cache_item = cache->out_args;
+        /* return a tuple */
+        py_out = PyTuple_New(total_out_args);
+        if (has_return) {
+            PyTuple_SET_ITEM(py_out, arg_index, py_return);
+            arg_index++;
+        }
+
+        for(; arg_index < total_out_args; arg_index++) {
+            PyGIArgCache *arg_cache = (PyGIArgCache *)cache_item->data;
+            PyObject *py_obj = arg_cache->out_marshaller(state,
+                                                         cache,
+                                                         arg_cache,
+                                                         &(state->out_values[arg_index]));
+
+            PyTuple_SET_ITEM(py_out, arg_index, py_obj);
+            cache_item = cache_item->next;
+        }
+    }
+    return py_out;
 }
 
 PyObject *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]