pygi-cache.c 28.5 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 "pyglib.h"
26
#include "pygi-info.h"
27
#include "pygi-cache.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
#include "pygi-struct-marshal.h"
38
#include "pygi-enum-marshal.h"
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60


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

61 62 63 64 65 66 67 68 69 70 71
/* 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
 */
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
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;
}

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

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

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

136
    g_function_invoker_destroy (&cache->invoker);
137 138 139 140 141 142
    g_slice_free (PyGICallableCache, cache);
}


/* PyGIInterfaceCache */

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

156 157 158 159 160 161 162 163 164 165 166 167
/* 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
 */
168 169 170 171 172 173 174
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)
175
{
176 177 178 179 180 181
    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
182
    }
183

184
    ( (PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
185

186 187 188 189 190 191
    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);
192

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

197
    return TRUE;
198 199
}

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

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

220 221 222 223 224 225 226 227 228
    return (PyGIArgCache *)ic;
}

/* PyGISequenceCache */

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

234 235 236 237 238 239 240 241 242 243 244 245 246
/* 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
 */
247 248 249 250 251 252
gboolean
pygi_arg_sequence_setup (PyGISequenceCache  *sc,
                         GITypeInfo         *type_info,
                         GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                         GITransfer          transfer,
                         PyGIDirection       direction)
253 254
{
    GITypeInfo *item_type_info;
255
    GITransfer item_transfer;
256

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

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

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

277 278
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

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

    return TRUE;
}

286
PyGIArgCache *
287
pygi_arg_cache_alloc (void)
288
{
289
    return g_slice_new0 (PyGIArgCache);
290
}
291

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

302 303
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

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

343
    return NULL;
344 345
}

346
PyGIArgCache *
347 348 349 350 351 352 353
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)
354
{
355
    PyGIArgCache *arg_cache = NULL;
356
    GITypeTag type_tag;
357

358 359
    type_tag = g_type_info_get_tag (type_info);

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

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

               pygi_arg_garray_len_arg_setup (arg_cache,
                                              type_info,
                                              callable_cache,
                                              direction,
                                              c_arg_index,
                                              &py_arg_index);
398
           }
399 400
           break;

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

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

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

               g_base_info_unref ( (GIBaseInfo *)interface_info);
433
           }
434
           break;
435

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

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

    return arg_cache;
450 451
}

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

469 470
/* Generate the cache for the callable's arguments */
static gboolean
471 472
_args_cache_generate (GICallableInfo *callable_info,
                      PyGICallableCache *callable_cache)
473
{
474 475
    gssize arg_index = 0;
    gssize i;
476
    GITypeInfo *return_info;
477
    GITransfer return_transfer;
478
    PyGIArgCache *return_cache;
479
    PyGIDirection return_direction;
Chun-wei Fan's avatar
Chun-wei Fan committed
480
	gssize last_explicit_arg_index;
481

482 483
    /* Return arguments are always considered out */
    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
484

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

501
    return_cache->is_skipped = g_callable_info_skip_return (callable_info);
502 503
    callable_cache->return_cache = return_cache;
    g_base_info_unref (return_info);
504

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

511
        interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
512 513

        instance_cache =
514
            _arg_cache_new_for_interface (interface_info,
515
                                          NULL,
516 517
                                          NULL,
                                          GI_TRANSFER_NOTHING,
518
                                          PYGI_DIRECTION_FROM_PYTHON,
519
                                          callable_cache);
520

521
        g_base_info_unref ( (GIBaseInfo *)interface_info);
522 523 524 525

        if (instance_cache == NULL)
            return FALSE;

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

532
        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
533

534
        arg_index++;
535
        callable_cache->n_py_args++;
536 537
    }

538

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

544 545 546 547
        arg_info = g_callable_info_get_arg (callable_info, i);

        if (g_arg_info_get_closure (arg_info) == i) {

548
            arg_cache = pygi_arg_cache_alloc ();
549
            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
550

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

556
        } else {
557
            GITypeInfo *type_info;
558

559 560 561 562 563 564 565 566 567 568
            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) {
569 570 571 572
                /* ensure c_arg_index always aligns with callable_cache->args_cache
                 * and all of the various PyGIInvokeState arrays. */
                arg_cache->c_arg_index = arg_index;

573 574 575 576
                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++;
                }
577

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

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

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

589 590 591 592
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    py_arg_index = callable_cache->n_py_args;
                    callable_cache->n_py_args++;
                }
593

594
                arg_cache =
595 596 597 598 599 600 601
                    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
602

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

609 610 611

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

613 614 615
                    callable_cache->to_py_args =
                        g_slist_append (callable_cache->to_py_args, arg_cache);
                }
616

617 618
                _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
            }
619

620
            g_base_info_unref (type_info);
621
        }
622

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

626
        g_base_info_unref ( (GIBaseInfo *)arg_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
627

628
    }
629

630 631 632 633 634 635
    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;
636 637
    callable_cache->user_data_varargs_index = -1;

Chun-wei Fan's avatar
Chun-wei Fan committed
638
    last_explicit_arg_index = -1;
639 640 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

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

            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;
            }
680 681
        }
    }
682

683
    return TRUE;
684 685
}

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
static gboolean
_setup_invoker (GICallableInfo *callable_info,
                GIInfoType info_type,
                GIFunctionInvoker *invoker,
                GCallback function_ptr)
{
    GError *error = NULL;

    if (info_type == GI_INFO_TYPE_FUNCTION) {
        if (g_function_info_prep_invoker ((GIFunctionInfo *)callable_info,
                                          invoker,
                                          &error)) {
            return TRUE;
        }
        if (!pyglib_error_check (&error)) {
            PyErr_Format (PyExc_RuntimeError,
                          "unknown error creating invoker for %s",
                          g_base_info_get_name ((GIBaseInfo *)callable_info));
        }
        return FALSE;

    } else {
        if (!g_function_invoker_new_for_address (function_ptr,
                                                 (GIFunctionInfo *)callable_info,
                                                 invoker,
                                                 &error)) {
            if (!pyglib_error_check (&error)) {
                PyErr_Format (PyExc_RuntimeError,
                              "unknown error creating invoker for %s",
                              g_base_info_get_name ((GIBaseInfo *)callable_info));
            }
            return FALSE;
        }
    }
    return TRUE;
}

723
PyGICallableCache *
724 725 726
pygi_callable_cache_new (GICallableInfo *callable_info,
                         GCallback function_ptr,
                         gboolean is_ccallback)
727
{
728
    gint n_args;
729
    PyGICallableCache *cache;
730
    GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
731

732 733
    cache = g_slice_new0 (PyGICallableCache);

734 735 736
    if (cache == NULL)
        return NULL;

737
    cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);
738
    cache->throws = g_callable_info_can_throw_gerror ((GIBaseInfo *)callable_info);
739

740 741 742 743 744
    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",
745
                                       g_base_info_get_namespace (callable_info), cache->name,
746 747 748
                                       deprecated);
        else
            warning = g_strdup_printf ("%s.%s is deprecated",
749
                                       g_base_info_get_namespace (callable_info), cache->name);
750
        PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
751
        g_free (warning);
752 753
    }

754 755 756 757 758 759 760 761 762 763 764 765
    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) {
766 767 768 769
        if (is_ccallback)
            cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
        else
            cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
770 771 772 773
    } else {
        cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
    }

774
    n_args = g_callable_info_get_n_args (callable_info);
775 776 777 778

    /* 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)
779
        n_args++;
780

781
    if (n_args >= 0) {
782
        cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) pygi_arg_cache_free);
783 784
        g_ptr_array_set_size (cache->args_cache, n_args);
    }
785

786
    if (!_args_cache_generate (callable_info, cache))
787 788
        goto err;

789 790 791 792
    if (!_setup_invoker (callable_info, type, &cache->invoker, function_ptr)) {
        goto err;
    }

793
    return cache;
794
err:
795
    pygi_callable_cache_free (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
796
    return NULL;
797
}