pygi-cache.c 26.9 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 28
#include "pygi-marshal-to-py.h"
#include "pygi-marshal-from-py.h"
29
#include "pygi-marshal-cleanup.h"
30
#include "pygi-type.h"
31
#include "pygi-hashtable.h"
32
#include "pygi-basictype.h"
33
#include "pygi-list.h"
34
#include "pygi-array.h"
35
#include "pygi-closure.h"
36
#include "pygi-error.h"
37
#include "pygi-object.h"
38
#include "pygi-struct-marshal.h"
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96


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

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

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

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
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
131
static void
132
_interface_cache_free_func (PyGIInterfaceCache *cache)
133 134
{
    if (cache != NULL) {
135
        Py_XDECREF (cache->py_type);
136
        if (cache->type_name != NULL)
137
            g_free (cache->type_name);
138
        if (cache->interface_info != NULL)
139 140
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
141 142 143
    }
}

144 145 146 147 148 149 150
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)
151
{
152 153 154 155 156 157
    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
158
    }
159

160
    ( (PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
161

162 163 164 165 166 167
    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);
168

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

173
    return TRUE;
174 175
}

176 177 178 179 180 181
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)
182 183
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
184

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

196 197 198 199 200 201 202 203 204 205 206 207
    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);
    }
208 209
}

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

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

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

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

240 241
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

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

    return TRUE;
}

249
PyGIArgCache *
250
_arg_cache_alloc (void)
251
{
252
    return g_slice_new0 (PyGIArgCache);
253
}
254

255
static void
256 257
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
258
{
259
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
260 261
}

262
static void
263 264
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
265
{
266
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
267
}
268

269
static void
270 271
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
272
{
273
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
274 275
}

276
static void
277 278
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
279
{
280
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
281 282
}

283

284
static PyGIArgCache *
285 286 287 288 289 290
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
291
{
292
    PyGIArgCache *arg_cache = NULL;
293
    GIInfoType info_type;
294

295 296
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

297 298 299 300 301 302 303 304 305
    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);
306
        }
307 308 309 310 311 312 313
        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);
314 315 316 317 318 319 320 321
        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);
322 323
        default:
            ;  /* pass through to old model of setup */
324 325
    }

326 327 328 329 330
    arg_cache = pygi_arg_interface_new_from_info (type_info,
                                                  arg_info,
                                                  transfer,
                                                  direction,
                                                  iface_info);
331 332 333
    if (arg_cache == NULL)
        return NULL;

334 335
    switch (info_type) {
        case GI_INFO_TYPE_ENUM:
336
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
337
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
338

339
            if (direction & PYGI_DIRECTION_TO_PYTHON)
340
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
341

342 343
            break;
        case GI_INFO_TYPE_FLAGS:
344
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
345
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
346

347
            if (direction & PYGI_DIRECTION_TO_PYTHON)
348
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
349

350 351
            break;
        default:
352
            g_assert_not_reached ();
353 354
    }

355
    return arg_cache;
356 357
}

358
PyGIArgCache *
359
_arg_cache_new (GITypeInfo *type_info,
360
                GIArgInfo *arg_info,     /* may be null */
361
                GITransfer transfer,
362
                PyGIDirection direction,
363
                gssize c_arg_index,
364 365
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
366
{
367
    PyGIArgCache *arg_cache = NULL;
368
    GITypeTag type_tag;
369

370 371
    type_tag = g_type_info_get_tag (type_info);

372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
    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:
388
       case GI_TYPE_TAG_FILENAME:
389 390 391 392 393
           arg_cache = pygi_arg_basic_type_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
           break;
394

395 396
       case GI_TYPE_TAG_ARRAY:
           {
397 398 399 400
               arg_cache = pygi_arg_garray_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
401
               if (arg_cache == NULL)
402 403 404 405 406 407 408 409
                   return NULL;

               pygi_arg_garray_len_arg_setup (arg_cache,
                                              type_info,
                                              callable_cache,
                                              direction,
                                              c_arg_index,
                                              &py_arg_index);
410
           }
411 412
           break;

413
       case GI_TYPE_TAG_GLIST:
414 415 416 417 418
           arg_cache = pygi_arg_glist_new_from_info (type_info,
                                                     arg_info,
                                                     transfer,
                                                     direction);
           break;
419

420
       case GI_TYPE_TAG_GSLIST:
421 422 423 424 425 426 427 428
           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,
429 430 431
                                                          arg_info,
                                                          transfer,
                                                          direction);
432
           break;
433

434
       case GI_TYPE_TAG_INTERFACE:
435
           {
436
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
437
               arg_cache = _arg_cache_new_for_interface (interface_info,
438
                                                         type_info,
439 440 441
                                                         arg_info,
                                                         transfer,
                                                         direction,
442
                                                         callable_cache);
443 444

               g_base_info_unref ( (GIBaseInfo *)interface_info);
445
           }
446
           break;
447

448 449 450 451 452
       case GI_TYPE_TAG_ERROR:
           arg_cache = pygi_arg_gerror_new_from_info (type_info,
                                                      arg_info,
                                                      transfer,
                                                      direction);
453 454 455
           break;
    }

456 457 458 459 460 461
    if (arg_cache != NULL) {
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
462 463
}

464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
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;
    }
}

481 482
/* Generate the cache for the callable's arguments */
static gboolean
483 484
_args_cache_generate (GICallableInfo *callable_info,
                      PyGICallableCache *callable_cache)
485
{
486 487
    gssize arg_index = 0;
    gssize i;
488
    GITypeInfo *return_info;
489
    GITransfer return_transfer;
490
    PyGIArgCache *return_cache;
491 492
    PyGIDirection return_direction;

493 494
    /* Return arguments are always considered out */
    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
495

496
    /* cache the return arg */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
497
    return_info =
498
        g_callable_info_get_return_type (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
499
    return_transfer =
500
        g_callable_info_get_caller_owns (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
501
    return_cache =
502 503 504
        _arg_cache_new (return_info,
                        NULL,
                        return_transfer,
505
                        return_direction,
506
                        -1,
507 508
                        -1,
                        callable_cache);
509 510
    if (return_cache == NULL)
        return FALSE;
511

512
    return_cache->is_skipped = g_callable_info_skip_return (callable_info);
513 514
    callable_cache->return_cache = return_cache;
    g_base_info_unref (return_info);
515

516
    /* first arg is the instance */
517 518
    if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
            callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
519 520 521
        GIInterfaceInfo *interface_info;
        PyGIArgCache *instance_cache;

522
        interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
523 524

        instance_cache =
525
            _arg_cache_new_for_interface (interface_info,
526
                                          NULL,
527 528
                                          NULL,
                                          GI_TRANSFER_NOTHING,
529
                                          PYGI_DIRECTION_FROM_PYTHON,
530
                                          callable_cache);
531

532
        g_base_info_unref ( (GIBaseInfo *)interface_info);
533 534 535 536

        if (instance_cache == NULL)
            return FALSE;

537 538 539
        /* Because we are not supplied a GITypeInfo for instance arguments,
         * assume some defaults. */
        instance_cache->is_pointer = TRUE;
540 541
        instance_cache->py_arg_index = 0;
        instance_cache->c_arg_index = 0;
542

543
        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
544

545
        arg_index++;
546
        callable_cache->n_from_py_args++;
547
        callable_cache->n_py_args++;
548 549
    }

550

551
    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
552
        PyGIArgCache *arg_cache = NULL;
553
        GIArgInfo *arg_info;
554
        PyGIDirection direction;
555

556 557 558 559 560
        arg_info = g_callable_info_get_arg (callable_info, i);

        if (g_arg_info_get_closure (arg_info) == i) {

            arg_cache = _arg_cache_alloc ();
561
            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
562

563 564
            direction = PYGI_DIRECTION_FROM_PYTHON;
            arg_cache->direction = direction;
565 566 567 568 569
            arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
            arg_cache->c_arg_index = i;

            callable_cache->n_from_py_args++;

570
        } else {
571
            GITypeInfo *type_info;
572

573 574 575 576 577 578 579 580 581 582 583 584 585 586
            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++;
                }
587

588 589 590 591
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    arg_cache->c_arg_index = callable_cache->n_from_py_args;
                    callable_cache->n_from_py_args++;
                }
592

593 594 595
                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                    callable_cache->n_to_py_args++;
                }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
596

597
                arg_cache->type_tag = g_type_info_get_tag (type_info);
598

599
            } else {
600 601 602 603
                GITransfer transfer;
                gssize py_arg_index = -1;
                transfer = g_arg_info_get_ownership_transfer (arg_info);

604 605 606 607 608
                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++;
                }
609

610 611 612 613 614 615
                arg_cache =
                    _arg_cache_new (type_info,
                                    arg_info,
                                    transfer,
                                    direction,
                                    arg_index,
616 617
                                    py_arg_index,
                                    callable_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
618

619 620 621 622 623
                if (arg_cache == NULL) {
                    g_base_info_unref( (GIBaseInfo *)type_info);
                    g_base_info_unref( (GIBaseInfo *)arg_info);
                    return FALSE;
                }
624

625 626 627

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

629 630 631
                    callable_cache->to_py_args =
                        g_slist_append (callable_cache->to_py_args, arg_cache);
                }
632

633 634
                _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
            }
635

636
            g_base_info_unref (type_info);
637
        }
638

639 640 641
        /* Ensure arguments always have a name when available */
        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);

642
        g_base_info_unref ( (GIBaseInfo *)arg_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
643

644
    }
645

646 647 648 649 650 651
    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;
652 653 654
    callable_cache->user_data_varargs_index = -1;

    gssize last_explicit_arg_index = -1;
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684

    /* 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;
            }
685 686 687 688 689 690 691 692 693 694 695

            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;
            }
696 697
        }
    }
698

699
    return TRUE;
700 701
}

702
PyGICallableCache *
703
_pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
704
{
705
    gint n_args;
706
    PyGICallableCache *cache;
707
    GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
708

709 710
    cache = g_slice_new0 (PyGICallableCache);

711 712 713
    if (cache == NULL)
        return NULL;

714 715
    cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);

716 717 718 719 720
    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",
721
                                       g_base_info_get_namespace (callable_info), cache->name,
722 723 724
                                       deprecated);
        else
            warning = g_strdup_printf ("%s.%s is deprecated",
725
                                       g_base_info_get_namespace (callable_info), cache->name);
726
        PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
727
        g_free (warning);
728 729
    }

730 731 732 733 734 735 736 737 738 739 740 741
    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) {
742 743 744 745
        if (is_ccallback)
            cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
        else
            cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
746 747 748 749
    } else {
        cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
    }

750
    n_args = g_callable_info_get_n_args (callable_info);
751 752 753 754

    /* 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)
755
        n_args++;
756

757 758 759 760
    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);
    }
761

762
    if (!_args_cache_generate (callable_info, cache))
763 764
        goto err;

765
    return cache;
766
err:
767
    _pygi_callable_cache_free (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
768
    return NULL;
769
}