pygi-cache.c 40.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* -*- Mode: C; c-basic-offset: 4 -*-
 * vim: tabstop=4 shiftwidth=4 expandtab
 *
 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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
 */
21

22 23
#include <girepository.h>

24
#include "pygi-info.h"
25
#include "pygi-cache.h"
26 27
#include "pygi-marshal-to-py.h"
#include "pygi-marshal-from-py.h"
28
#include "pygi-marshal-cleanup.h"
29
#include "pygi-type.h"
30
#include "pygi-hashtable.h"
31
#include "pygi-basictype.h"
32

33 34

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
35
                                             GITypeInfo *type_info,
36 37
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
38
                                             PyGIDirection direction,
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
                                             /* will be removed */
                                             PyGICallableCache *callable_cache);


/* _arg_info_default_value
 * info:
 * arg: (out): GIArgument to fill in with default value.
 *
 * This is currently a place holder API which only supports "allow-none" pointer args.
 * Once defaults are part of the GI API, we can replace this with: g_arg_info_default_value
 * https://bugzilla.gnome.org/show_bug.cgi?id=558620
 *
 * Returns: TRUE if the given argument supports a default value and was filled in.
 */
static gboolean
_arg_info_default_value (GIArgInfo *info, GIArgument *arg)
{
    if (g_arg_info_may_be_null (info)) {
        arg->v_pointer = NULL;
        return TRUE;
    }
    return FALSE;
}

gboolean
pygi_arg_base_setup (PyGIArgCache *arg_cache,
                     GITypeInfo   *type_info,
                     GIArgInfo    *arg_info,  /* may be NULL for return arguments */
                     GITransfer    transfer,
                     PyGIDirection direction)
{
    arg_cache->direction = direction;
    arg_cache->transfer = transfer;
    arg_cache->py_arg_index = -1;
    arg_cache->c_arg_index = -1;

    if (type_info != NULL) {
        arg_cache->is_pointer = g_type_info_is_pointer (type_info);
        arg_cache->type_tag = g_type_info_get_tag (type_info);
        g_base_info_ref ( (GIBaseInfo *) type_info);
        arg_cache->type_info = type_info;
    }

    if (arg_info != NULL) {
        if (!arg_cache->has_default) {
            /* It is possible has_default was set somewhere else */
            arg_cache->has_default = _arg_info_default_value (arg_info,
                                                              &arg_cache->default_value);
        }
        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
        arg_cache->allow_none = g_arg_info_may_be_null (arg_info);

        if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE || arg_cache->type_tag == GI_TYPE_TAG_ARRAY)
            arg_cache->is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
        else
            arg_cache->is_caller_allocates = FALSE;
    }
    return TRUE;
}


gboolean
pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
                          GITypeInfo         *type_info,
                          GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                          GITransfer          transfer,
                          PyGIDirection       direction,
                          GIInterfaceInfo    *iface_info)
{
    if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }

    g_base_info_ref ( (GIBaseInfo *)iface_info);
    iface_cache->interface_info = iface_info;
    iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE;

    return TRUE;
}

123

124
/* cleanup */
125
void
126
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
127 128 129 130
{
    if (cache == NULL)
        return;

131
    if (cache->type_info != NULL)
132
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
133
    if (cache->destroy_notify)
134
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
135
    else
136
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
137 138 139
}

static void
140
_interface_cache_free_func (PyGIInterfaceCache *cache)
141 142
{
    if (cache != NULL) {
143
        Py_XDECREF (cache->py_type);
144
        if (cache->type_name != NULL)
145
            g_free (cache->type_name);
146
        if (cache->interface_info != NULL)
147 148
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
149 150 151 152
    }
}


153
static void
154
_sequence_cache_free_func (PyGISequenceCache *cache)
155
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
156
    if (cache != NULL) {
157 158
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
159
    }
160 161
}

162
static void
163
_callback_cache_free_func (PyGICallbackCache *cache)
164
{
165 166
    if (cache != NULL) {
        if (cache->interface_info != NULL)
167
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
168

169
        g_slice_free (PyGICallbackCache, cache);
170
    }
171 172 173
}

void
174
_pygi_callable_cache_free (PyGICallableCache *cache)
175
{
176 177 178
    if (cache == NULL)
        return;

179
    g_slist_free (cache->to_py_args);
180 181
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);
182
    g_ptr_array_unref (cache->args_cache);
183

184
    if (cache->return_cache != NULL)
185
        _pygi_arg_cache_free (cache->return_cache);
186

187
    g_slice_free (PyGICallableCache, cache);
188 189 190 191
}

/* cache generation */

192 193
static PyGIInterfaceCache *
_interface_cache_new (GIInterfaceInfo *iface_info)
194 195
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
196

197 198
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
199
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
200
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
201 202 203 204

    if (ic->py_type == NULL)
        return NULL;

205
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
206 207 208
    return ic;
}

209 210 211 212 213
static PyGISequenceCache *
_sequence_cache_new (GITypeInfo *type_info,
                     GIDirection direction,
                     GITransfer transfer,
                     gssize child_offset)
214 215 216
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
217
    GITransfer item_transfer;
218

219 220
    sc = g_slice_new0 (PyGISequenceCache);
    ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
221

222
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
223 224 225 226
    sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
    sc->len_arg_index = g_type_info_get_array_length (type_info);
    if (sc->len_arg_index >= 0)
        sc->len_arg_index += child_offset;
227

228 229
    item_type_info = g_type_info_get_param_type (type_info, 0);

230 231
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
232

233 234 235 236
    sc->item_cache = _arg_cache_new (item_type_info,
                                     NULL,
                                     item_transfer,
                                     direction,
237 238
                                     0, 0,
                                     NULL);
239

240
    if (sc->item_cache == NULL) {
241
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
242 243
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
244

245 246
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
247

248
    return sc;
249 250
}

251 252 253 254
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
                     GIInterfaceInfo *iface_info,
                     gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
255 256 257
{
   PyGICallbackCache *cc;

258
   cc = g_slice_new0 (PyGICallbackCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
259 260
   ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

261
   cc->user_data_index = g_arg_info_get_closure (arg_info);
262
   if (cc->user_data_index != -1)
263
       cc->user_data_index += child_offset;
264
   cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
265
   if (cc->destroy_notify_index != -1)
266
       cc->destroy_notify_index += child_offset;
267
   cc->scope = g_arg_info_get_scope (arg_info);
268 269
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
270 271 272
   return cc;
}

273
PyGIArgCache *
274
_arg_cache_alloc (void)
275
{
276
    return g_slice_new0 (PyGIArgCache);
277
}
278 279


280 281
static PyGIArgCache*
_arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
282
                                PyGICallableCache *callable_cache,
283
                                PyGIDirection direction,
284 285
                                gssize arg_index,
                                gssize *py_arg_index)
286
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
287
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
288
    if (seq_cache->len_arg_index >= 0) {
289
        PyGIArgCache *child_cache = NULL;
290

291 292
        child_cache = _pygi_callable_cache_get_arg (callable_cache,
                                                    seq_cache->len_arg_index);
293
        if (child_cache == NULL) {
294
            child_cache = _arg_cache_alloc ();
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
        } else {
            /* If the "length" arg cache already exists (the length comes before
             * the array in the argument list), remove it from the to_py_args list
             * because it does not belong in "to python" return tuple. The length
             * will implicitly be a part of the returned Python list.
             */
            if (direction & PYGI_DIRECTION_TO_PYTHON) {
                callable_cache->to_py_args =
                    g_slist_remove (callable_cache->to_py_args, child_cache);
            }

            /* This is a case where the arg cache already exists and has been
             * setup by another array argument sharing the same length argument.
             * See: gi_marshalling_tests_multi_array_key_value_in
             */
            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
                return child_cache;
312 313
        }

314 315 316 317 318
        /* There is a length argument for this array, so increment the number
         * of "to python" child arguments when applicable.
         */
        if (direction & PYGI_DIRECTION_TO_PYTHON)
             callable_cache->n_to_py_child_args++;
319

320
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
321
        child_cache->direction = direction;
322 323
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
324

325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
        /* ugly edge case code:
         *
         * When the length comes before the array parameter we need to update
         * indexes of arguments after the index argument.
         */
        if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
            gssize i;
            (*py_arg_index) -= 1;
            callable_cache->n_py_args -= 1;

            for (i = seq_cache->len_arg_index + 1;
                   i < _pygi_callable_cache_args_len (callable_cache); i++) {
                PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
                if (update_cache == NULL)
                    break;

                update_cache->py_arg_index -= 1;
            }
        }

345
        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
346
        return child_cache;
347 348
    }

349 350
    return NULL;
}
351

352 353 354 355 356 357 358 359 360 361 362 363
static gboolean
_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                PyGICallableCache *callable_cache,
                                GITypeInfo *type_info,
                                GITransfer transfer,
                                PyGIDirection direction,
                                gssize arg_index)
{
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
    seq_cache->array_type = g_type_info_get_array_type (type_info);
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
364
    return TRUE;
365 366
}

367
static gboolean
368 369 370 371 372 373
_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                              PyGICallableCache *callable_cache,
                              GITypeInfo *type_info,
                              GITransfer transfer,
                              PyGIDirection direction,
                              gssize arg_index)
374
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
375
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
376
    seq_cache->array_type = g_type_info_get_array_type (type_info);
377 378
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
379 380 381
    return TRUE;
}

382
static void
383 384
_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
                                GITransfer transfer)
385
{
386 387
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
388
}
389

390
static void
391 392
_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
                              GITransfer transfer)
393
{
394 395
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
396 397
}

398
static void
399 400
_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
401
{
402 403
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
404
}
405

406
static void
407 408
_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
409
{
410 411
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
412 413
}

414
static void
415
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
416
{
417
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
418
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
419 420
}

421
static void
422
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
423
{
424
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
425
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
426 427
}

428
static void
429 430
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
431
{
432
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
433 434
}

435
static void
436 437
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
438
{
439
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
440 441
}

442
static void
443 444 445
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
446
{
447
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
448
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
449
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
450 451

    if (iface_cache->g_type == G_TYPE_VALUE)
452
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
453
    else if (iface_cache->is_foreign)
454
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
455
}
456

457
static void
458 459 460
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
461 462
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
463
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
464
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
465 466

    if (iface_cache->is_foreign)
467
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
468 469
}

470
static void
471 472
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
473
{
474 475
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
476 477
}

478
static void
479 480
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
481
{
482
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object_cache_adapter;
483
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
484 485
}

486
static void
487 488
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
489
{
490
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
491
    if (callback_cache->user_data_index >= 0) {
492
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
493
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
494
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
495
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
496 497
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->user_data_index,
                                      user_data_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
498
    }
499 500

    if (callback_cache->destroy_notify_index >= 0) {
501
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
502
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
503
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
504 505
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
                                      destroy_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
506
    }
507
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
508
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
509 510
}

511
static void
512
_arg_cache_to_py_interface_callback_setup (void)
513
{
514 515 516
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
517

518
static void
519 520
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
521
{
522
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
523 524
}

525
static void
526 527
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
528
{
529
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
530
}
531

532
static void
533 534
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
535
{
536
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
537 538
}

539
static void
540 541
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
542
{
543
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
544 545
}

546

547
PyGIArgCache *
548 549 550 551 552 553
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
554
{
555
    PyGIArgCache *arg_cache = NULL;
556
    gssize child_offset = 0;
557
    GIInfoType info_type;
558 559 560 561 562

    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                 callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
563

564 565
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

566
    /* Callbacks are special cased */
567 568
    if (info_type == GI_INFO_TYPE_CALLBACK) {
        PyGICallbackCache *callback_cache;
569

570 571 572 573 574 575 576 577 578 579 580
        if (direction & PYGI_DIRECTION_TO_PYTHON) {
            _arg_cache_to_py_interface_callback_setup ();
            return NULL;
        }

        callback_cache =
            _callback_cache_new (arg_info,
                                 iface_info,
                                 child_offset);

        arg_cache = (PyGIArgCache *)callback_cache;
581 582
        if (arg_cache == NULL)
            return NULL;
583 584 585 586 587 588 589 590 591 592 593 594

        pygi_arg_base_setup (arg_cache,
                             type_info,
                             arg_info,
                             transfer,
                             direction);

        if (direction & PYGI_DIRECTION_FROM_PYTHON)
            _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);

        return arg_cache;

595 596
    }

597 598 599 600
    arg_cache = (PyGIArgCache *)_interface_cache_new (iface_info);
    if (arg_cache == NULL)
        return NULL;

601 602
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
603
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
604
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
605

606
            if (direction & PYGI_DIRECTION_TO_PYTHON)
607
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
608

609
            break;
610
        case GI_INFO_TYPE_BOXED:
611
        case GI_INFO_TYPE_STRUCT:
612
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
613 614 615 616
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

617
            if (direction & PYGI_DIRECTION_TO_PYTHON)
618 619 620
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
621 622 623
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
624
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
625
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
626

627
            if (direction & PYGI_DIRECTION_TO_PYTHON)
628
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
629

630 631
            break;
        case GI_INFO_TYPE_ENUM:
632
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
633
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
634

635
            if (direction & PYGI_DIRECTION_TO_PYTHON)
636
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
637

638 639
            break;
        case GI_INFO_TYPE_FLAGS:
640
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
641
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
642

643
            if (direction & PYGI_DIRECTION_TO_PYTHON)
644
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
645

646 647
            break;
        default:
648
            g_assert_not_reached ();
649 650
    }

651 652 653 654 655 656
    pygi_arg_interface_setup ((PyGIInterfaceCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction,
                              iface_info);
657 658

    return arg_cache;
659 660
}

661
PyGIArgCache *
662
_arg_cache_new (GITypeInfo *type_info,
663
                GIArgInfo *arg_info,     /* may be null */
664
                GITransfer transfer,
665
                PyGIDirection direction,
666
                gssize c_arg_index,
667 668
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
669
{
670
    PyGIArgCache *arg_cache = NULL;
671
    gssize child_offset = 0;
672
    GITypeTag type_tag;
673

674 675
    type_tag = g_type_info_get_tag (type_info);

676 677 678 679
    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
680

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
       case GI_TYPE_TAG_BOOLEAN:
       case GI_TYPE_TAG_INT8:
       case GI_TYPE_TAG_UINT8:
       case GI_TYPE_TAG_INT16:
       case GI_TYPE_TAG_UINT16:
       case GI_TYPE_TAG_INT32:
       case GI_TYPE_TAG_UINT32:
       case GI_TYPE_TAG_INT64:
       case GI_TYPE_TAG_UINT64:
       case GI_TYPE_TAG_FLOAT:
       case GI_TYPE_TAG_DOUBLE:
       case GI_TYPE_TAG_UNICHAR:
       case GI_TYPE_TAG_GTYPE:
       case GI_TYPE_TAG_UTF8:
697
       case GI_TYPE_TAG_FILENAME:
698 699 700 701 702 703 704 705
           arg_cache = pygi_arg_basic_type_new_from_info (type_info, arg_info, transfer, direction);
           if (arg_cache) {
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
           } else {
               return NULL;
           }
706

707 708
       case GI_TYPE_TAG_ARRAY:
           {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
709
               PyGISequenceCache *seq_cache =
710 711 712 713
                   _sequence_cache_new (type_info,
                                        direction,
                                        transfer,
                                        child_offset);
714 715 716 717 718

               arg_cache = (PyGIArgCache *)seq_cache;
               if (arg_cache == NULL)
                   break;

719
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
720 721 722 723
                   _arg_cache_from_py_array_setup (arg_cache,
                                                   callable_cache,
                                                   type_info,
                                                   transfer,
724 725
                                                   direction,
                                                   c_arg_index);
726

727
               if (direction & PYGI_DIRECTION_TO_PYTHON)
728 729 730 731 732 733
                   _arg_cache_to_py_array_setup (arg_cache,
                                                 callable_cache,
                                                 type_info,
                                                 transfer,
                                                 direction,
                                                 c_arg_index);
734

735 736 737 738 739
               _arg_cache_array_len_arg_setup (arg_cache,
                                               callable_cache,
                                               direction,
                                               c_arg_index,
                                               &py_arg_index);
740

741 742 743 744
               break;
           }
       case GI_TYPE_TAG_GLIST:
           {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
745
               PyGISequenceCache *seq_cache =
746 747 748 749
                   _sequence_cache_new (type_info,
                                        direction,
                                        transfer,
                                        child_offset);
750

751 752 753
               arg_cache = (PyGIArgCache *)seq_cache;
               if (arg_cache == NULL)
                   break;
754

755
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
756
                   _arg_cache_from_py_glist_setup (arg_cache, transfer);
757

758
               if (direction & PYGI_DIRECTION_TO_PYTHON)
759
                   _arg_cache_to_py_glist_setup (arg_cache, transfer);
760 761 762


               break;
763 764
           }
       case GI_TYPE_TAG_GSLIST:
765
           {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
766
               PyGISequenceCache *seq_cache =
767 768 769 770
                   _sequence_cache_new (type_info,
                                        direction,
                                        transfer,
                                        child_offset);
771 772 773 774 775

               arg_cache = (PyGIArgCache *)seq_cache;
               if (arg_cache == NULL)
                   break;

776
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
777
                   _arg_cache_from_py_gslist_setup (arg_cache, transfer);
778

779
               if (direction & PYGI_DIRECTION_TO_PYTHON)
780
                   _arg_cache_to_py_gslist_setup (arg_cache, transfer);
781 782 783

               break;
            }
784
       case GI_TYPE_TAG_GHASH:
785 786 787 788
           arg_cache = pygi_arg_hash_table_new_from_info (type_info, arg_info, transfer, direction);
           arg_cache->py_arg_index = py_arg_index;
           arg_cache->c_arg_index = c_arg_index;
           return arg_cache;
789

790
       case GI_TYPE_TAG_INTERFACE:
791
           {
792
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
793
               arg_cache = _arg_cache_new_for_interface (interface_info,
794
                                                         type_info,
795 796 797
                                                         arg_info,
                                                         transfer,
                                                         direction,
798
                                                         callable_cache);
799 800

               g_base_info_unref ( (GIBaseInfo *)interface_info);
801 802 803
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
804
           }
805
       case GI_TYPE_TAG_ERROR:
806
           arg_cache = _arg_cache_alloc ();
807 808 809
           if (arg_cache == NULL)
               break;

810
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
811
               _arg_cache_from_py_gerror_setup (arg_cache);
812

813
           if (direction & PYGI_DIRECTION_TO_PYTHON)
814
               _arg_cache_to_py_gerror_setup (arg_cache);
815

816 817 818
           break;
    }

819
    if (arg_cache != NULL) {