pygi-cache.c 33.6 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
#include "pygi-list.h"
33
#include "pygi-array.h"
34

35 36

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
37
                                             GITypeInfo *type_info,
38 39
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
40
                                             PyGIDirection direction,
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 123 124
                                             /* 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;
}

125

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

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

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


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

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

171
        g_slice_free (PyGICallbackCache, cache);
172
    }
173 174 175
}

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

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

186
    if (cache->return_cache != NULL)
187
        _pygi_arg_cache_free (cache->return_cache);
188

189
    g_slice_free (PyGICallableCache, cache);
190 191 192 193
}

/* cache generation */

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

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

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

207
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
208 209 210
    return ic;
}

211 212 213 214 215 216
gboolean
pygi_arg_sequence_setup (PyGISequenceCache  *sc,
                         GITypeInfo         *type_info,
                         GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                         GITransfer          transfer,
                         PyGIDirection       direction)
217 218
{
    GITypeInfo *item_type_info;
219
    GITransfer item_transfer;
220

221 222 223 224 225 226 227
    if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }
228

229
    sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
230
    item_type_info = g_type_info_get_param_type (type_info, 0);
231 232
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
233

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

241 242
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

243
    if (sc->item_cache == NULL) {
244 245 246 247 248 249
        return FALSE;
    }

    return TRUE;
}

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

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

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

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

278
static void
279
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
280
{
281
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
282
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
283 284
}

285
static void
286
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
287
{
288
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
289
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
290 291
}

292
static void
293 294
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
295
{
296
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
297 298
}

299
static void
300 301
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
302
{
303
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
304 305
}

306
static void
307 308 309
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
310
{
311
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
312
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
313
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
314 315

    if (iface_cache->g_type == G_TYPE_VALUE)
316
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
317
    else if (iface_cache->is_foreign)
318
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
319
}
320

321
static void
322 323 324
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
325 326
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
327
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
328
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
329 330

    if (iface_cache->is_foreign)
331
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
332 333
}

334
static void
335 336
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
337
{
338 339
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
340 341
}

342
static void
343 344
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
345
{
346
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object_cache_adapter;
347
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
348 349
}

350
static void
351 352
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
353
{
354
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
355
    if (callback_cache->user_data_index >= 0) {
356
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
357
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
358
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
359
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
360 361
        _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
362
    }
363 364

    if (callback_cache->destroy_notify_index >= 0) {
365
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
366
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
367
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
368 369
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
                                      destroy_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
370
    }
371
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
372
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
373 374
}

375
static void
376
_arg_cache_to_py_interface_callback_setup (void)
377
{
378 379 380
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
381

382
static void
383 384
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
385
{
386
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
387 388
}

389
static void
390 391
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
392
{
393
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
394
}
395

396
static void
397 398
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
399
{
400
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
401 402
}

403
static void
404 405
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
406
{
407
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
408 409
}

410

411
PyGIArgCache *
412 413 414 415 416 417
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
418
{
419
    PyGIArgCache *arg_cache = NULL;
420
    gssize child_offset = 0;
421
    GIInfoType info_type;
422 423 424 425 426

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

428 429
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

430
    /* Callbacks are special cased */
431 432
    if (info_type == GI_INFO_TYPE_CALLBACK) {
        PyGICallbackCache *callback_cache;
433

434 435 436 437 438 439 440 441 442 443 444
        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;
445 446
        if (arg_cache == NULL)
            return NULL;
447 448 449 450 451 452 453 454 455 456 457 458

        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;

459 460
    }

461 462 463 464
    arg_cache = (PyGIArgCache *)_interface_cache_new (iface_info);
    if (arg_cache == NULL)
        return NULL;

465 466
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
467
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
468
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
469

470
            if (direction & PYGI_DIRECTION_TO_PYTHON)
471
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
472

473
            break;
474
        case GI_INFO_TYPE_BOXED:
475
        case GI_INFO_TYPE_STRUCT:
476
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
477 478 479 480
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

481
            if (direction & PYGI_DIRECTION_TO_PYTHON)
482 483 484
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
485 486 487
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
488
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
489
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
490

491
            if (direction & PYGI_DIRECTION_TO_PYTHON)
492
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
493

494 495
            break;
        case GI_INFO_TYPE_ENUM:
496
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
497
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
498

499
            if (direction & PYGI_DIRECTION_TO_PYTHON)
500
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
501

502 503
            break;
        case GI_INFO_TYPE_FLAGS:
504
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
505
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
506

507
            if (direction & PYGI_DIRECTION_TO_PYTHON)
508
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
509

510 511
            break;
        default:
512
            g_assert_not_reached ();
513 514
    }

515 516 517 518 519 520
    pygi_arg_interface_setup ((PyGIInterfaceCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction,
                              iface_info);
521 522

    return arg_cache;
523 524
}

525
PyGIArgCache *
526
_arg_cache_new (GITypeInfo *type_info,
527
                GIArgInfo *arg_info,     /* may be null */
528
                GITransfer transfer,
529
                PyGIDirection direction,
530
                gssize c_arg_index,
531 532
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
533
{
534
    PyGIArgCache *arg_cache = NULL;
535
    GITypeTag type_tag;
536

537 538
    type_tag = g_type_info_get_tag (type_info);

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
    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:
555
       case GI_TYPE_TAG_FILENAME:
556 557 558 559 560 561 562 563
           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;
           }
564

565 566
       case GI_TYPE_TAG_ARRAY:
           {
567 568 569 570
               arg_cache = pygi_arg_garray_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
571
               if (arg_cache == NULL)
572 573 574 575 576 577 578 579
                   return NULL;

               pygi_arg_garray_len_arg_setup (arg_cache,
                                              type_info,
                                              callable_cache,
                                              direction,
                                              c_arg_index,
                                              &py_arg_index);
580

581 582 583
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
584 585 586
           }
       case GI_TYPE_TAG_GLIST:
           {
587 588 589 590
               arg_cache = pygi_arg_glist_new_from_info (type_info,
                                                         arg_info,
                                                         transfer,
                                                         direction);
591
               if (arg_cache == NULL)
592
                   return NULL;
593

594 595 596
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
597 598
           }
       case GI_TYPE_TAG_GSLIST:
599
           {
600 601 602 603
               arg_cache = pygi_arg_gslist_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
604
               if (arg_cache == NULL)
605
                   return NULL;
606

607 608 609
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
610
            }
611
       case GI_TYPE_TAG_GHASH:
612 613 614 615
           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;
616

617
       case GI_TYPE_TAG_INTERFACE:
618
           {
619
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
620
               arg_cache = _arg_cache_new_for_interface (interface_info,
621
                                                         type_info,
622 623 624
                                                         arg_info,
                                                         transfer,
                                                         direction,
625
                                                         callable_cache);
626 627

               g_base_info_unref ( (GIBaseInfo *)interface_info);
628 629 630
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
631
           }
632
       case GI_TYPE_TAG_ERROR:
633
           arg_cache = _arg_cache_alloc ();
634 635 636
           if (arg_cache == NULL)
               break;

637
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
638
               _arg_cache_from_py_gerror_setup (arg_cache);
639

640
           if (direction & PYGI_DIRECTION_TO_PYTHON)
641
               _arg_cache_to_py_gerror_setup (arg_cache);
642

643 644 645
           break;
    }

646
    if (arg_cache != NULL) {
647
        pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction);
648 649 650 651 652
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
653 654
}

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
static PyGIDirection
_pygi_get_direction (PyGICallableCache *callable_cache, GIDirection gi_direction)
{
    /* For vfuncs and callbacks our marshalling directions are reversed */
    if (gi_direction == GI_DIRECTION_INOUT) {
        return PYGI_DIRECTION_BIDIRECTIONAL;
    } else if (gi_direction == GI_DIRECTION_IN) {
        if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
            return PYGI_DIRECTION_TO_PYTHON;
        return PYGI_DIRECTION_FROM_PYTHON;
    } else {
        if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
            return PYGI_DIRECTION_FROM_PYTHON;
        return PYGI_DIRECTION_TO_PYTHON;
    }
}

672 673
/* Generate the cache for the callable's arguments */
static gboolean
674 675
_args_cache_generate (GICallableInfo *callable_info,
                      PyGICallableCache *callable_cache)
676
{
677 678
    gssize arg_index = 0;
    gssize i;
679
    GITypeInfo *return_info;
680
    GITransfer return_transfer;
681
    PyGIArgCache *return_cache;
682 683
    PyGIDirection return_direction;

684 685
    /* Return arguments are always considered out */
    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
686

687
    /* cache the return arg */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
688
    return_info =
689
        g_callable_info_get_return_type (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
690
    return_transfer =
691
        g_callable_info_get_caller_owns (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
692
    return_cache =
693 694 695
        _arg_cache_new (return_info,
                        NULL,
                        return_transfer,
696
                        return_direction,
697
                        -1,
698 699
                        -1,
                        callable_cache);
700 701
    if (return_cache == NULL)
        return FALSE;
702

703
    return_cache->is_skipped = g_callable_info_skip_return (callable_info);
704 705
    callable_cache->return_cache = return_cache;
    g_base_info_unref (return_info);
706

707
    /* first arg is the instance */
708 709
    if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
            callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
710 711 712
        GIInterfaceInfo *interface_info;
        PyGIArgCache *instance_cache;

713
        interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
714 715

        instance_cache =
716
            _arg_cache_new_for_interface (interface_info,
717
                                          NULL,
718 719
                                          NULL,
                                          GI_TRANSFER_NOTHING,
720
                                          PYGI_DIRECTION_FROM_PYTHON,
721
                                          callable_cache);
722

723
        g_base_info_unref ( (GIBaseInfo *)interface_info);
724 725 726 727

        if (instance_cache == NULL)
            return FALSE;

728 729 730
        /* Because we are not supplied a GITypeInfo for instance arguments,
         * assume some defaults. */
        instance_cache->is_pointer = TRUE;
731 732
        instance_cache->py_arg_index = 0;
        instance_cache->c_arg_index = 0;
733

734
        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
735

736
        arg_index++;
737
        callable_cache->n_from_py_args++;
738
        callable_cache->n_py_args++;
739 740
    }

741

742
    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
743
        PyGIArgCache *arg_cache = NULL;
744
        GIArgInfo *arg_info;
745
        PyGIDirection direction;
746

747 748 749 750 751
        arg_info = g_callable_info_get_arg (callable_info, i);

        if (g_arg_info_get_closure (arg_info) == i) {

            arg_cache = _arg_cache_alloc ();
752
            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
753

754 755
            direction = PYGI_DIRECTION_FROM_PYTHON;
            arg_cache->direction = direction;
756 757 758 759 760
            arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
            arg_cache->c_arg_index = i;

            callable_cache->n_from_py_args++;

761
        } else {
762
            GITypeInfo *type_info;
763

764 765 766 767 768 769 770 771 772 773 774 775 776 777
            direction = _pygi_get_direction (callable_cache,
                                             g_arg_info_get_direction (arg_info));
            type_info = g_arg_info_get_type (arg_info);

            /* must be an child arg filled in by its owner
             * and continue
             * fill in it's c_arg_index, add to the in count
             */
            arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index);
            if (arg_cache != NULL) {
                if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
                    arg_cache->py_arg_index = callable_cache->n_py_args;
                    callable_cache->n_py_args++;
                }
778

779 780 781 782
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    arg_cache->c_arg_index = callable_cache->n_from_py_args;
                    callable_cache->n_from_py_args++;
                }
783

784 785 786
                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                    callable_cache->n_to_py_args++;
                }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
787

788
                arg_cache->type_tag = g_type_info_get_tag (type_info);
789

790
            } else {
791 792 793 794
                GITransfer transfer;
                gssize py_arg_index = -1;
                transfer = g_arg_info_get_ownership_transfer (arg_info);

795 796 797 798 799
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    py_arg_index = callable_cache->n_py_args;
                    callable_cache->n_from_py_args++;
                    callable_cache->n_py_args++;
                }
800

801 802 803 804 805 806
                arg_cache =
                    _arg_cache_new (type_info,
                                    arg_info,
                                    transfer,
                                    direction,
                                    arg_index,
807 808
                                    py_arg_index,
                                    callable_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
809

810 811 812 813 814
                if (arg_cache == NULL) {
                    g_base_info_unref( (GIBaseInfo *)type_info);
                    g_base_info_unref( (GIBaseInfo *)arg_info);
                    return FALSE;
                }
815

816 817