pygi-cache.c 29.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
#include "pygi-list.h"
33
#include "pygi-array.h"
34
#include "pygi-closure.h"
35
#include "pygi-error.h"
36
#include "pygi-object.h"
37 38 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


/* _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;
}

95
void
96
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
97 98 99 100
{
    if (cache == NULL)
        return;

101
    if (cache->type_info != NULL)
102
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
103
    if (cache->destroy_notify)
104
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
105
    else
106
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
107 108
}

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
void
_pygi_callable_cache_free (PyGICallableCache *cache)
{
    if (cache == NULL)
        return;

    g_slist_free (cache->to_py_args);
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);
    g_ptr_array_unref (cache->args_cache);

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

    g_slice_free (PyGICallableCache, cache);
}


/* PyGIInterfaceCache */

John (J5) Palmieri's avatar
John (J5) Palmieri committed
129
static void
130
_interface_cache_free_func (PyGIInterfaceCache *cache)
131 132
{
    if (cache != NULL) {
133
        Py_XDECREF (cache->py_type);
134
        if (cache->type_name != NULL)
135
            g_free (cache->type_name);
136
        if (cache->interface_info != NULL)
137 138
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
139 140 141
    }
}

142 143 144 145 146 147 148
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)
149
{
150 151 152 153 154 155
    if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
156
    }
157

158
    ( (PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
159

160 161 162 163 164 165
    g_base_info_ref ( (GIBaseInfo *)iface_info);
    iface_cache->interface_info = iface_info;
    iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE;
    iface_cache->type_name = _pygi_g_base_info_get_fullname (iface_info);
    iface_cache->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
    iface_cache->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
166

167 168 169
    if (iface_cache->py_type == NULL) {
        return FALSE;
    }
170

171
    return TRUE;
172 173
}

174 175 176 177 178 179
PyGIArgCache *
pygi_arg_interface_new_from_info (GITypeInfo         *type_info,
                                  GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                                  GITransfer          transfer,
                                  PyGIDirection       direction,
                                  GIInterfaceInfo    *iface_info)
180 181
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
182

183
    ic = g_slice_new0 (PyGIInterfaceCache);
184 185 186 187 188 189 190
    if (!pygi_arg_interface_setup (ic,
                                   type_info,
                                   arg_info,
                                   transfer,
                                   direction,
                                   iface_info)) {
        _pygi_arg_cache_free ((PyGIArgCache *)ic);
191
        return NULL;
192
    }
193

194 195 196 197 198 199 200 201 202 203 204 205
    return (PyGIArgCache *)ic;
}

/* PyGISequenceCache */

static void
_sequence_cache_free_func (PyGISequenceCache *cache)
{
    if (cache != NULL) {
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
    }
206 207
}

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

218 219 220 221 222 223 224
    if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }
225

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

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

238 239
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

240
    if (sc->item_cache == NULL) {
241 242 243 244 245 246
        return FALSE;
    }

    return TRUE;
}

247
PyGIArgCache *
248
_arg_cache_alloc (void)
249
{
250
    return g_slice_new0 (PyGIArgCache);
251
}
252

253
static void
254 255
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
256
{
257
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
258 259
}

260
static void
261 262
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
263
{
264
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
265 266
}

267
static void
268 269 270
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
271
{
272
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
273
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
274
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
275 276

    if (iface_cache->g_type == G_TYPE_VALUE)
277
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
278
    else if (iface_cache->is_foreign)
279
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
280
}
281

282
static void
283 284 285
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
286 287
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
288
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
289
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
290 291

    if (iface_cache->is_foreign)
292
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
293 294
}

295
static void
296 297
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
298
{
299
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
300 301
}

302
static void
303 304
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
305
{
306
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
307
}
308

309
static void
310 311
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
312
{
313
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
314 315
}

316
static void
317 318
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
319
{
320
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
321 322
}

323

324
static PyGIArgCache *
325 326 327 328 329 330
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
331
{
332
    PyGIArgCache *arg_cache = NULL;
333
    GIInfoType info_type;
334

335 336
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

337 338 339 340 341 342 343 344 345
    switch (info_type) {
        case GI_INFO_TYPE_CALLBACK:
        {
            return pygi_arg_callback_new_from_info (type_info,
                                                    arg_info,
                                                    transfer,
                                                    direction,
                                                    iface_info,
                                                    callable_cache);
346
        }
347 348 349 350 351 352 353
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
            return pygi_arg_gobject_new_from_info (type_info,
                                                   arg_info,
                                                   transfer,
                                                   direction,
                                                   iface_info);
354 355
        default:
            ;  /* pass through to old model of setup */
356 357
    }

358 359 360 361 362
    arg_cache = pygi_arg_interface_new_from_info (type_info,
                                                  arg_info,
                                                  transfer,
                                                  direction,
                                                  iface_info);
363 364 365
    if (arg_cache == NULL)
        return NULL;

366 367
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
368
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
369
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
370

371
            if (direction & PYGI_DIRECTION_TO_PYTHON)
372
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
373

374
            break;
375
        case GI_INFO_TYPE_BOXED:
376
        case GI_INFO_TYPE_STRUCT:
377
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
378 379 380 381
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

382
            if (direction & PYGI_DIRECTION_TO_PYTHON)
383 384 385
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
386 387
            break;
        case GI_INFO_TYPE_ENUM:
388
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
389
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
390

391
            if (direction & PYGI_DIRECTION_TO_PYTHON)
392
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
393

394 395
            break;
        case GI_INFO_TYPE_FLAGS:
396
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
397
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
398

399
            if (direction & PYGI_DIRECTION_TO_PYTHON)
400
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
401

402 403
            break;
        default:
404
            g_assert_not_reached ();
405 406
    }

407
    return arg_cache;
408 409
}

410
PyGIArgCache *
411
_arg_cache_new (GITypeInfo *type_info,
412
                GIArgInfo *arg_info,     /* may be null */
413
                GITransfer transfer,
414
                PyGIDirection direction,
415
                gssize c_arg_index,
416 417
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
418
{
419
    PyGIArgCache *arg_cache = NULL;
420
    GITypeTag type_tag;
421

422 423
    type_tag = g_type_info_get_tag (type_info);

424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    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:
440
       case GI_TYPE_TAG_FILENAME:
441 442 443 444 445
           arg_cache = pygi_arg_basic_type_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
           break;
446

447 448
       case GI_TYPE_TAG_ARRAY:
           {
449 450 451 452
               arg_cache = pygi_arg_garray_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
453
               if (arg_cache == NULL)
454 455 456 457 458 459 460 461
                   return NULL;

               pygi_arg_garray_len_arg_setup (arg_cache,
                                              type_info,
                                              callable_cache,
                                              direction,
                                              c_arg_index,
                                              &py_arg_index);
462
           }
463 464
           break;

465
       case GI_TYPE_TAG_GLIST:
466 467 468 469 470
           arg_cache = pygi_arg_glist_new_from_info (type_info,
                                                     arg_info,
                                                     transfer,
                                                     direction);
           break;
471

472
       case GI_TYPE_TAG_GSLIST:
473 474 475 476 477 478 479 480
           arg_cache = pygi_arg_gslist_new_from_info (type_info,
                                                      arg_info,
                                                      transfer,
                                                      direction);
           break;

       case GI_TYPE_TAG_GHASH:
           arg_cache = pygi_arg_hash_table_new_from_info (type_info,
481 482 483
                                                          arg_info,
                                                          transfer,
                                                          direction);
484
           break;
485

486
       case GI_TYPE_TAG_INTERFACE:
487
           {
488
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
489
               arg_cache = _arg_cache_new_for_interface (interface_info,
490
                                                         type_info,
491 492 493
                                                         arg_info,
                                                         transfer,
                                                         direction,
494
                                                         callable_cache);
495 496

               g_base_info_unref ( (GIBaseInfo *)interface_info);
497
           }
498
           break;
499

500 501 502 503 504
       case GI_TYPE_TAG_ERROR:
           arg_cache = pygi_arg_gerror_new_from_info (type_info,
                                                      arg_info,
                                                      transfer,
                                                      direction);
505 506 507
           break;
    }

508 509 510 511 512 513
    if (arg_cache != NULL) {
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
514 515
}

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
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;
    }
}

533 534
/* Generate the cache for the callable's arguments */
static gboolean
535 536
_args_cache_generate (GICallableInfo *callable_info,
                      PyGICallableCache *callable_cache)
537
{
538 539
    gssize arg_index = 0;
    gssize i;
540
    GITypeInfo *return_info;
541
    GITransfer return_transfer;
542
    PyGIArgCache *return_cache;
543 544
    PyGIDirection return_direction;

545 546
    /* Return arguments are always considered out */
    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
547

548
    /* cache the return arg */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
549
    return_info =
550
        g_callable_info_get_return_type (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
551
    return_transfer =
552
        g_callable_info_get_caller_owns (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
553
    return_cache =
554 555 556
        _arg_cache_new (return_info,
                        NULL,
                        return_transfer,
557
                        return_direction,
558
                        -1,
559 560
                        -1,
                        callable_cache);
561 562
    if (return_cache == NULL)
        return FALSE;
563

564
    return_cache->is_skipped = g_callable_info_skip_return (callable_info);
565 566
    callable_cache->return_cache = return_cache;
    g_base_info_unref (return_info);
567

568
    /* first arg is the instance */
569 570
    if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
            callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
571 572 573
        GIInterfaceInfo *interface_info;
        PyGIArgCache *instance_cache;

574
        interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
575 576

        instance_cache =
577
            _arg_cache_new_for_interface (interface_info,
578
                                          NULL,
579 580
                                          NULL,
                                          GI_TRANSFER_NOTHING,
581
                                          PYGI_DIRECTION_FROM_PYTHON,
582
                                          callable_cache);
583

584
        g_base_info_unref ( (GIBaseInfo *)interface_info);
585 586 587 588

        if (instance_cache == NULL)
            return FALSE;

589 590 591
        /* Because we are not supplied a GITypeInfo for instance arguments,
         * assume some defaults. */
        instance_cache->is_pointer = TRUE;
592 593
        instance_cache->py_arg_index = 0;
        instance_cache->c_arg_index = 0;
594

595
        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
596

597
        arg_index++;
598
        callable_cache->n_from_py_args++;
599
        callable_cache->n_py_args++;
600 601
    }

602

603
    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
604
        PyGIArgCache *arg_cache = NULL;
605
        GIArgInfo *arg_info;
606
        PyGIDirection direction;
607

608 609 610 611 612
        arg_info = g_callable_info_get_arg (callable_info, i);

        if (g_arg_info_get_closure (arg_info) == i) {

            arg_cache = _arg_cache_alloc ();
613
            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
614

615 616
            direction = PYGI_DIRECTION_FROM_PYTHON;
            arg_cache->direction = direction;
617 618 619 620 621
            arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
            arg_cache->c_arg_index = i;

            callable_cache->n_from_py_args++;

622
        } else {
623
            GITypeInfo *type_info;
624

625 626 627 628 629 630 631 632 633 634 635 636 637 638
            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++;
                }
639

640 641 642 643
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    arg_cache->c_arg_index = callable_cache->n_from_py_args;
                    callable_cache->n_from_py_args++;
                }
644

645 646 647
                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                    callable_cache->n_to_py_args++;
                }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
648

649
                arg_cache->type_tag = g_type_info_get_tag (type_info);
650

651
            } else {
652 653 654 655
                GITransfer transfer;
                gssize py_arg_index = -1;
                transfer = g_arg_info_get_ownership_transfer (arg_info);

656 657 658 659 660
                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++;
                }
661

662 663 664 665 666 667
                arg_cache =
                    _arg_cache_new (type_info,
                                    arg_info,
                                    transfer,
                                    direction,
                                    arg_index,
668 669
                                    py_arg_index,
                                    callable_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
670

671 672 673 674 675
                if (arg_cache == NULL) {
                    g_base_info_unref( (GIBaseInfo *)type_info);
                    g_base_info_unref( (GIBaseInfo *)arg_info);
                    return FALSE;
                }
676

677 678 679

                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                    callable_cache->n_to_py_args++;
680

681 682 683
                    callable_cache->to_py_args =
                        g_slist_append (callable_cache->to_py_args, arg_cache);
                }
684

685 686
                _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
            }
687

688
            g_base_info_unref (type_info);
689
        }
690

691 692 693
        /* Ensure arguments always have a name when available */
        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);

694
        g_base_info_unref ( (GIBaseInfo *)arg_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
695

696
    }
697

698 699 700 701 702 703
    if (callable_cache->arg_name_hash == NULL) {
        callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
    } else {
        g_hash_table_remove_all (callable_cache->arg_name_hash);
    }
    callable_cache->n_py_required_args = 0;
704 705 706
    callable_cache->user_data_varargs_index = -1;

    gssize last_explicit_arg_index = -1;
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736

    /* Reverse loop through all the arguments to setup arg_name_list/hash
     * and find the number of required arguments */
    for (i=((gssize)_pygi_callable_cache_args_len (callable_cache))-1; i >= 0; i--) {
        PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, i);

        if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
                arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
                arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {

            /* Setup arg_name_list and arg_name_hash */
            gpointer arg_name = (gpointer)arg_cache->arg_name;
            callable_cache->arg_name_list = g_slist_prepend (callable_cache->arg_name_list,
                                                             arg_name);
            if (arg_name != NULL) {
                g_hash_table_insert (callable_cache->arg_name_hash,
                                     arg_name,
                                     GINT_TO_POINTER(i));
            }

            /* The first tail argument without a default will force all the preceding
             * argument defaults off. This limits support of default args to the
             * tail of an args list.
             */
            if (callable_cache->n_py_required_args > 0) {
                arg_cache->has_default = FALSE;
                callable_cache->n_py_required_args += 1;
            } else if (!arg_cache->has_default) {
                callable_cache->n_py_required_args += 1;
            }
737 738 739 740 741 742 743 744 745 746 747

            if (last_explicit_arg_index == -1) {
                last_explicit_arg_index = i;

                /* If the last "from python" argument in the args list is a child
                 * with pyarg (currently only callback user_data). Set it to eat
                 * variable args in the callable cache.
                 */
                if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG)
                    callable_cache->user_data_varargs_index = i;
            }
748 749
        }
    }
750

751
    return TRUE;
752 753
}

754
PyGICallableCache *
755
_pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
756
{
757
    gint n_args;
758
    PyGICallableCache *cache;
759
    GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
760

761 762
    cache = g_slice_new0 (PyGICallableCache);

763 764 765
    if (cache == NULL)
        return NULL;

766 767
    cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);

768 769 770 771 772
    if (g_base_info_is_deprecated (callable_info)) {
        const gchar *deprecated = g_base_info_get_attribute (callable_info, "deprecated");
        gchar *warning;
        if (deprecated != NULL)
            warning = g_strdup_printf ("%s.%s is deprecated: %s",
773
                                       g_base_info_get_namespace (callable_info), cache->name,
774 775 776
                                       deprecated);
        else
            warning = g_strdup_printf ("%s.%s is deprecated",
777
                                       g_base_info_get_namespace (callable_info), cache->name);
778
        PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
779
        g_free (warning);
780 781
    }

782 783 784 785 786 787 788 789 790 791 792 793
    if (type == GI_INFO_TYPE_FUNCTION) {
        GIFunctionInfoFlags flags;

        flags = g_function_info_get_flags ( (GIFunctionInfo *)callable_info);

        if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
            cache->function_type = PYGI_FUNCTION_TYPE_CONSTRUCTOR;
        else if (flags & GI_FUNCTION_IS_METHOD)
            cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
    } else if (type == GI_INFO_TYPE_VFUNC) {
        cache->function_type = PYGI_FUNCTION_TYPE_VFUNC;
    } else if (type == GI_INFO_TYPE_CALLBACK) {
794 795 796 797
        if (is_ccallback)
            cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
        else
            cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
798 799 800 801
    } else {
        cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
    }

802
    n_args = g_callable_info_get_n_args (callable_info);
803 804 805 806

    /* if we are a method or vfunc make sure the instance parameter is counted */
    if (cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
            cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
807
        n_args++;
808

809 810 811 812
    if (n_args >= 0) {
        cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) _pygi_arg_cache_free);
        g_ptr_array_set_size (cache->args_cache, n_args);
    }
813

814
    if (!_args_cache_generate (callable_info, cache))
815 816
        goto err;

817
    return cache;
818
err:
819
    _pygi_callable_cache_free (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
820
    return NULL;
821
}