pygi-cache.c 27 KB
Newer Older
1 2 3 4
/* -*- Mode: C; c-basic-offset: 4 -*-
 * vim: tabstop=4 shiftwidth=4 expandtab
 *
 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5
 * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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
 */
22

23 24
#include <girepository.h>

25
#include "pygi-info.h"
26
#include "pygi-cache.h"
27
#include "pygi-marshal-cleanup.h"
28
#include "pygi-type.h"
29
#include "pygi-hashtable.h"
30
#include "pygi-basictype.h"
31
#include "pygi-list.h"
32
#include "pygi-array.h"
33
#include "pygi-closure.h"
34
#include "pygi-error.h"
35
#include "pygi-object.h"
36
#include "pygi-struct-marshal.h"
37
#include "pygi-enum-marshal.h"
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59


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

60 61 62 63 64 65 66 67 68 69 70
/* pygi_arg_base_setup:
 * arg_cache: argument cache to initialize
 * type_info: source for type related attributes to cache
 * arg_info: (allow-none): source for argument related attributes to cache
 * transfer: transfer mode to store in the argument cache
 * direction: marshaling direction to store in the cache
 *
 * Initializer for PyGIArgCache
 *
 * Returns: TRUE on success and FALSE on failure
 */
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
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;
}

107
void
108
pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
109 110 111 112
{
    if (cache == NULL)
        return;

113
    if (cache->type_info != NULL)
114
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
115
    if (cache->destroy_notify)
116
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
117
    else
118
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
119 120
}

121
void
122
pygi_callable_cache_free (PyGICallableCache *cache)
123 124 125 126 127 128 129 130 131 132
{
    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)
133
        pygi_arg_cache_free (cache->return_cache);
134 135 136 137 138 139 140

    g_slice_free (PyGICallableCache, cache);
}


/* PyGIInterfaceCache */

John (J5) Palmieri's avatar
John (J5) Palmieri committed
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 156 157 158 159 160 161 162 163 164 165
/* pygi_arg_interface_setup:
 * arg_cache: argument cache to initialize
 * type_info: source for type related attributes to cache
 * arg_info: (allow-none): source for argument related attributes to cache
 * transfer: transfer mode to store in the argument cache
 * direction: marshaling direction to store in the cache
 * iface_info: interface info to cache
 *
 * Initializer for PyGIInterfaceCache
 *
 * Returns: TRUE on success and FALSE on failure
 */
166 167 168 169 170 171 172
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)
173
{
174 175 176 177 178 179
    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
180
    }
181

182
    ( (PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
183

184 185 186 187 188 189
    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);
190

191 192 193
    if (iface_cache->py_type == NULL) {
        return FALSE;
    }
194

195
    return TRUE;
196 197
}

198 199 200 201 202 203
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)
204 205
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
206

207
    ic = g_slice_new0 (PyGIInterfaceCache);
208 209 210 211 212 213
    if (!pygi_arg_interface_setup (ic,
                                   type_info,
                                   arg_info,
                                   transfer,
                                   direction,
                                   iface_info)) {
214
        pygi_arg_cache_free ((PyGIArgCache *)ic);
215
        return NULL;
216
    }
217

218 219 220 221 222 223 224 225 226
    return (PyGIArgCache *)ic;
}

/* PyGISequenceCache */

static void
_sequence_cache_free_func (PyGISequenceCache *cache)
{
    if (cache != NULL) {
227
        pygi_arg_cache_free (cache->item_cache);
228 229
        g_slice_free (PyGISequenceCache, cache);
    }
230 231
}

232 233 234 235 236 237 238 239 240 241 242 243 244
/* pygi_arg_sequence_setup:
 * sc: sequence cache to initialize
 * type_info: source for type related attributes to cache
 * arg_info: (allow-none): source for argument related attributes to cache
 * transfer: transfer mode to store in the argument cache
 * direction: marshaling direction to store in the cache
 * iface_info: interface info to cache
 *
 * Initializer for PyGISequenceCache used for holding list and array argument
 * caches.
 *
 * Returns: TRUE on success and FALSE on failure
 */
245 246 247 248 249 250
gboolean
pygi_arg_sequence_setup (PyGISequenceCache  *sc,
                         GITypeInfo         *type_info,
                         GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                         GITransfer          transfer,
                         PyGIDirection       direction)
251 252
{
    GITypeInfo *item_type_info;
253
    GITransfer item_transfer;
254

255 256 257 258 259 260 261
    if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }
262

263
    sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
264
    item_type_info = g_type_info_get_param_type (type_info, 0);
265 266
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
267

268 269 270 271 272 273
    sc->item_cache = pygi_arg_cache_new (item_type_info,
                                         NULL,
                                         item_transfer,
                                         direction,
                                         0, 0,
                                         NULL);
274

275 276
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

277
    if (sc->item_cache == NULL) {
278 279 280 281 282 283
        return FALSE;
    }

    return TRUE;
}

284
PyGIArgCache *
285
pygi_arg_cache_alloc (void)
286
{
287
    return g_slice_new0 (PyGIArgCache);
288
}
289

290
static PyGIArgCache *
291 292 293 294 295 296
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
297
{
298
    GIInfoType info_type;
299

300 301
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

302 303 304 305 306 307 308 309
    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);
310 311 312 313 314 315 316
        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);
317 318 319 320 321 322 323 324
        case GI_INFO_TYPE_BOXED:
        case GI_INFO_TYPE_STRUCT:
        case GI_INFO_TYPE_UNION:
            return pygi_arg_struct_new_from_info (type_info,
                                                  arg_info,
                                                  transfer,
                                                  direction,
                                                  iface_info);
325
        case GI_INFO_TYPE_ENUM:
326 327 328 329 330
            return pygi_arg_enum_new_from_info (type_info,
                                                arg_info,
                                                transfer,
                                                direction,
                                                iface_info);
331
        case GI_INFO_TYPE_FLAGS:
332 333 334 335 336
            return pygi_arg_flags_new_from_info (type_info,
                                                 arg_info,
                                                 transfer,
                                                 direction,
                                                 iface_info);
337
        default:
338
            g_assert_not_reached ();
339 340
    }

341
    return NULL;
342 343
}

344
PyGIArgCache *
345 346 347 348 349 350 351
pygi_arg_cache_new (GITypeInfo *type_info,
                    GIArgInfo *arg_info,     /* may be null */
                    GITransfer transfer,
                    PyGIDirection direction,
                    gssize c_arg_index,
                    gssize py_arg_index,
                    PyGICallableCache *callable_cache)
352
{
353
    PyGIArgCache *arg_cache = NULL;
354
    GITypeTag type_tag;
355

356 357
    type_tag = g_type_info_get_tag (type_info);

358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
    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:
374
       case GI_TYPE_TAG_FILENAME:
375 376 377 378 379
           arg_cache = pygi_arg_basic_type_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
           break;
380

381 382
       case GI_TYPE_TAG_ARRAY:
           {
383 384 385 386
               arg_cache = pygi_arg_garray_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
387
               if (arg_cache == NULL)
388 389 390 391 392 393 394 395
                   return NULL;

               pygi_arg_garray_len_arg_setup (arg_cache,
                                              type_info,
                                              callable_cache,
                                              direction,
                                              c_arg_index,
                                              &py_arg_index);
396
           }
397 398
           break;

399
       case GI_TYPE_TAG_GLIST:
400 401 402 403 404
           arg_cache = pygi_arg_glist_new_from_info (type_info,
                                                     arg_info,
                                                     transfer,
                                                     direction);
           break;
405

406
       case GI_TYPE_TAG_GSLIST:
407 408 409 410 411 412 413 414
           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,
415 416 417
                                                          arg_info,
                                                          transfer,
                                                          direction);
418
           break;
419

420
       case GI_TYPE_TAG_INTERFACE:
421
           {
422
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
423
               arg_cache = _arg_cache_new_for_interface (interface_info,
424
                                                         type_info,
425 426 427
                                                         arg_info,
                                                         transfer,
                                                         direction,
428
                                                         callable_cache);
429 430

               g_base_info_unref ( (GIBaseInfo *)interface_info);
431
           }
432
           break;
433

434 435 436 437 438
       case GI_TYPE_TAG_ERROR:
           arg_cache = pygi_arg_gerror_new_from_info (type_info,
                                                      arg_info,
                                                      transfer,
                                                      direction);
439 440 441
           break;
    }

442 443 444 445 446 447
    if (arg_cache != NULL) {
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
448 449
}

450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
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;
    }
}

467 468
/* Generate the cache for the callable's arguments */
static gboolean
469 470
_args_cache_generate (GICallableInfo *callable_info,
                      PyGICallableCache *callable_cache)
471
{
472 473
    gssize arg_index = 0;
    gssize i;
474
    GITypeInfo *return_info;
475
    GITransfer return_transfer;
476
    PyGIArgCache *return_cache;
477 478
    PyGIDirection return_direction;

479 480
    /* Return arguments are always considered out */
    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
481

482
    /* cache the return arg */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
483
    return_info =
484
        g_callable_info_get_return_type (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
485
    return_transfer =
486
        g_callable_info_get_caller_owns (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
487
    return_cache =
488 489 490 491 492 493 494
        pygi_arg_cache_new (return_info,
                            NULL,
                            return_transfer,
                            return_direction,
                            -1,
                            -1,
                            callable_cache);
495 496
    if (return_cache == NULL)
        return FALSE;
497

498
    return_cache->is_skipped = g_callable_info_skip_return (callable_info);
499 500
    callable_cache->return_cache = return_cache;
    g_base_info_unref (return_info);
501

502
    /* first arg is the instance */
503 504
    if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
            callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
505 506 507
        GIInterfaceInfo *interface_info;
        PyGIArgCache *instance_cache;

508
        interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
509 510

        instance_cache =
511
            _arg_cache_new_for_interface (interface_info,
512
                                          NULL,
513 514
                                          NULL,
                                          GI_TRANSFER_NOTHING,
515
                                          PYGI_DIRECTION_FROM_PYTHON,
516
                                          callable_cache);
517

518
        g_base_info_unref ( (GIBaseInfo *)interface_info);
519 520 521 522

        if (instance_cache == NULL)
            return FALSE;

523 524 525
        /* Because we are not supplied a GITypeInfo for instance arguments,
         * assume some defaults. */
        instance_cache->is_pointer = TRUE;
526 527
        instance_cache->py_arg_index = 0;
        instance_cache->c_arg_index = 0;
528

529
        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
530

531
        arg_index++;
532
        callable_cache->n_from_py_args++;
533
        callable_cache->n_py_args++;
534 535
    }

536

537
    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
538
        PyGIArgCache *arg_cache = NULL;
539
        GIArgInfo *arg_info;
540
        PyGIDirection direction;
541

542 543 544 545
        arg_info = g_callable_info_get_arg (callable_info, i);

        if (g_arg_info_get_closure (arg_info) == i) {

546
            arg_cache = pygi_arg_cache_alloc ();
547
            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
548

549 550
            direction = PYGI_DIRECTION_FROM_PYTHON;
            arg_cache->direction = direction;
551 552 553 554 555
            arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
            arg_cache->c_arg_index = i;

            callable_cache->n_from_py_args++;

556
        } else {
557
            GITypeInfo *type_info;
558

559 560 561 562 563 564 565 566 567 568 569 570 571 572
            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++;
                }
573

574 575 576 577
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    arg_cache->c_arg_index = callable_cache->n_from_py_args;
                    callable_cache->n_from_py_args++;
                }
578

579 580 581
                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                    callable_cache->n_to_py_args++;
                }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
582

583
                arg_cache->type_tag = g_type_info_get_tag (type_info);
584

585
            } else {
586 587 588 589
                GITransfer transfer;
                gssize py_arg_index = -1;
                transfer = g_arg_info_get_ownership_transfer (arg_info);

590 591 592 593 594
                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++;
                }
595

596
                arg_cache =
597 598 599 600 601 602 603
                    pygi_arg_cache_new (type_info,
                                        arg_info,
                                        transfer,
                                        direction,
                                        arg_index,
                                        py_arg_index,
                                        callable_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
604

605 606 607 608 609
                if (arg_cache == NULL) {
                    g_base_info_unref( (GIBaseInfo *)type_info);
                    g_base_info_unref( (GIBaseInfo *)arg_info);
                    return FALSE;
                }
610

611 612 613

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

615 616 617
                    callable_cache->to_py_args =
                        g_slist_append (callable_cache->to_py_args, arg_cache);
                }
618

619 620
                _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
            }
621

622
            g_base_info_unref (type_info);
623
        }
624

625 626 627
        /* Ensure arguments always have a name when available */
        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);

628
        g_base_info_unref ( (GIBaseInfo *)arg_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
629

630
    }
631

632 633 634 635 636 637
    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;
638 639 640
    callable_cache->user_data_varargs_index = -1;

    gssize last_explicit_arg_index = -1;
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670

    /* 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;
            }
671 672 673 674 675 676 677 678 679 680 681

            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;
            }
682 683
        }
    }
684

685
    return TRUE;
686 687
}

688
PyGICallableCache *
689
pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
690
{
691
    gint n_args;
692
    PyGICallableCache *cache;
693
    GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
694

695 696
    cache = g_slice_new0 (PyGICallableCache);

697 698 699
    if (cache == NULL)
        return NULL;

700 701
    cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);

702 703 704 705 706
    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",
707
                                       g_base_info_get_namespace (callable_info), cache->name,
708 709 710
                                       deprecated);
        else
            warning = g_strdup_printf ("%s.%s is deprecated",
711
                                       g_base_info_get_namespace (callable_info), cache->name);
712
        PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
713
        g_free (warning);
714 715
    }

716 717 718 719 720 721 722 723 724 725 726 727
    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) {
728 729 730 731
        if (is_ccallback)
            cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
        else
            cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
732 733 734 735
    } else {
        cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
    }

736
    n_args = g_callable_info_get_n_args (callable_info);
737 738 739 740

    /* 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)
741
        n_args++;
742

743
    if (n_args >= 0) {
744
        cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) pygi_arg_cache_free);
745 746
        g_ptr_array_set_size (cache->args_cache, n_args);
    }
747

748
    if (!_args_cache_generate (callable_info, cache))
749 750
        goto err;

751
    return cache;
752
err:
753
    pygi_callable_cache_free (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
754
    return NULL;
755
}