pygi-cache.c 25.7 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 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


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

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

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

110
void
111
pygi_callable_cache_free (PyGICallableCache *cache)
112 113 114 115 116 117 118 119 120 121
{
    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)
122
        pygi_arg_cache_free (cache->return_cache);
123 124 125 126 127 128 129

    g_slice_free (PyGICallableCache, cache);
}


/* PyGIInterfaceCache */

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

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

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

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

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

172
    return TRUE;
173 174
}

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

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

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

/* PyGISequenceCache */

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

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

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

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

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

239 240
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

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

    return TRUE;
}

248
PyGIArgCache *
249
pygi_arg_cache_alloc (void)
250
{
251
    return g_slice_new0 (PyGIArgCache);
252
}
253

254
static PyGIArgCache *
255 256 257 258 259 260
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
261
{
262
    GIInfoType info_type;
263

264 265
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

266 267 268 269 270 271 272 273
    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);
274 275 276 277 278 279 280
        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);
281 282 283 284 285 286 287 288
        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);
289
        case GI_INFO_TYPE_ENUM:
290 291 292 293 294
            return pygi_arg_enum_new_from_info (type_info,
                                                arg_info,
                                                transfer,
                                                direction,
                                                iface_info);
295
        case GI_INFO_TYPE_FLAGS:
296 297 298 299 300
            return pygi_arg_flags_new_from_info (type_info,
                                                 arg_info,
                                                 transfer,
                                                 direction,
                                                 iface_info);
301
        default:
302
            g_assert_not_reached ();
303 304
    }

305
    return NULL;
306 307
}

308
PyGIArgCache *
309 310 311 312 313 314 315
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)
316
{
317
    PyGIArgCache *arg_cache = NULL;
318
    GITypeTag type_tag;
319

320 321
    type_tag = g_type_info_get_tag (type_info);

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    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:
338
       case GI_TYPE_TAG_FILENAME:
339 340 341 342 343
           arg_cache = pygi_arg_basic_type_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
           break;
344

345 346
       case GI_TYPE_TAG_ARRAY:
           {
347 348 349 350
               arg_cache = pygi_arg_garray_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
351
               if (arg_cache == NULL)
352 353 354 355 356 357 358 359
                   return NULL;

               pygi_arg_garray_len_arg_setup (arg_cache,
                                              type_info,
                                              callable_cache,
                                              direction,
                                              c_arg_index,
                                              &py_arg_index);
360
           }
361 362
           break;

363
       case GI_TYPE_TAG_GLIST:
364 365 366 367 368
           arg_cache = pygi_arg_glist_new_from_info (type_info,
                                                     arg_info,
                                                     transfer,
                                                     direction);
           break;
369

370
       case GI_TYPE_TAG_GSLIST:
371 372 373 374 375 376 377 378
           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,
379 380 381
                                                          arg_info,
                                                          transfer,
                                                          direction);
382
           break;
383

384
       case GI_TYPE_TAG_INTERFACE:
385
           {
386
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
387
               arg_cache = _arg_cache_new_for_interface (interface_info,
388
                                                         type_info,
389 390 391
                                                         arg_info,
                                                         transfer,
                                                         direction,
392
                                                         callable_cache);
393 394

               g_base_info_unref ( (GIBaseInfo *)interface_info);
395
           }
396
           break;
397

398 399 400 401 402
       case GI_TYPE_TAG_ERROR:
           arg_cache = pygi_arg_gerror_new_from_info (type_info,
                                                      arg_info,
                                                      transfer,
                                                      direction);
403 404 405
           break;
    }

406 407 408 409 410 411
    if (arg_cache != NULL) {
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
412 413
}

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
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;
    }
}

431 432
/* Generate the cache for the callable's arguments */
static gboolean
433 434
_args_cache_generate (GICallableInfo *callable_info,
                      PyGICallableCache *callable_cache)
435
{
436 437
    gssize arg_index = 0;
    gssize i;
438
    GITypeInfo *return_info;
439
    GITransfer return_transfer;
440
    PyGIArgCache *return_cache;
441 442
    PyGIDirection return_direction;

443 444
    /* Return arguments are always considered out */
    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
445

446
    /* cache the return arg */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
447
    return_info =
448
        g_callable_info_get_return_type (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
449
    return_transfer =
450
        g_callable_info_get_caller_owns (callable_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
451
    return_cache =
452 453 454 455 456 457 458
        pygi_arg_cache_new (return_info,
                            NULL,
                            return_transfer,
                            return_direction,
                            -1,
                            -1,
                            callable_cache);
459 460
    if (return_cache == NULL)
        return FALSE;
461

462
    return_cache->is_skipped = g_callable_info_skip_return (callable_info);
463 464
    callable_cache->return_cache = return_cache;
    g_base_info_unref (return_info);
465

466
    /* first arg is the instance */
467 468
    if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
            callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
469 470 471
        GIInterfaceInfo *interface_info;
        PyGIArgCache *instance_cache;

472
        interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
473 474

        instance_cache =
475
            _arg_cache_new_for_interface (interface_info,
476
                                          NULL,
477 478
                                          NULL,
                                          GI_TRANSFER_NOTHING,
479
                                          PYGI_DIRECTION_FROM_PYTHON,
480
                                          callable_cache);
481

482
        g_base_info_unref ( (GIBaseInfo *)interface_info);
483 484 485 486

        if (instance_cache == NULL)
            return FALSE;

487 488 489
        /* Because we are not supplied a GITypeInfo for instance arguments,
         * assume some defaults. */
        instance_cache->is_pointer = TRUE;
490 491
        instance_cache->py_arg_index = 0;
        instance_cache->c_arg_index = 0;
492

493
        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
494

495
        arg_index++;
496
        callable_cache->n_from_py_args++;
497
        callable_cache->n_py_args++;
498 499
    }

500

501
    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
502
        PyGIArgCache *arg_cache = NULL;
503
        GIArgInfo *arg_info;
504
        PyGIDirection direction;
505

506 507 508 509
        arg_info = g_callable_info_get_arg (callable_info, i);

        if (g_arg_info_get_closure (arg_info) == i) {

510
            arg_cache = pygi_arg_cache_alloc ();
511
            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
512

513 514
            direction = PYGI_DIRECTION_FROM_PYTHON;
            arg_cache->direction = direction;
515 516 517 518 519
            arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
            arg_cache->c_arg_index = i;

            callable_cache->n_from_py_args++;

520
        } else {
521
            GITypeInfo *type_info;
522

523 524 525 526 527 528 529 530 531 532 533 534 535 536
            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++;
                }
537

538 539 540 541
                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
                    arg_cache->c_arg_index = callable_cache->n_from_py_args;
                    callable_cache->n_from_py_args++;
                }
542

543 544 545
                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                    callable_cache->n_to_py_args++;
                }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
546

547
                arg_cache->type_tag = g_type_info_get_tag (type_info);
548

549
            } else {
550 551 552 553
                GITransfer transfer;
                gssize py_arg_index = -1;
                transfer = g_arg_info_get_ownership_transfer (arg_info);

554 555 556 557 558
                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++;
                }
559

560
                arg_cache =
561 562 563 564 565 566 567
                    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
568

569 570 571 572 573
                if (arg_cache == NULL) {
                    g_base_info_unref( (GIBaseInfo *)type_info);
                    g_base_info_unref( (GIBaseInfo *)arg_info);
                    return FALSE;
                }
574

575 576 577

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

579 580 581
                    callable_cache->to_py_args =
                        g_slist_append (callable_cache->to_py_args, arg_cache);
                }
582

583 584
                _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
            }
585

586
            g_base_info_unref (type_info);
587
        }
588

589 590 591
        /* Ensure arguments always have a name when available */
        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);

592
        g_base_info_unref ( (GIBaseInfo *)arg_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
593

594
    }
595

596 597 598 599 600 601
    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;
602 603 604
    callable_cache->user_data_varargs_index = -1;

    gssize last_explicit_arg_index = -1;
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634

    /* 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;
            }
635 636 637 638 639 640 641 642 643 644 645

            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;
            }
646 647
        }
    }
648

649
    return TRUE;
650 651
}

652
PyGICallableCache *
653
pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
654
{
655
    gint n_args;
656
    PyGICallableCache *cache;
657
    GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
658

659 660
    cache = g_slice_new0 (PyGICallableCache);

661 662 663
    if (cache == NULL)
        return NULL;

664 665
    cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);

666 667 668 669 670
    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",
671
                                       g_base_info_get_namespace (callable_info), cache->name,
672 673 674
                                       deprecated);
        else
            warning = g_strdup_printf ("%s.%s is deprecated",
675
                                       g_base_info_get_namespace (callable_info), cache->name);
676
        PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
677
        g_free (warning);
678 679
    }

680 681 682 683 684 685 686 687 688 689 690 691
    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) {
692 693 694 695
        if (is_ccallback)
            cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
        else
            cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
696 697 698 699
    } else {
        cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
    }

700
    n_args = g_callable_info_get_n_args (callable_info);
701 702 703 704

    /* 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)
705
        n_args++;
706

707
    if (n_args >= 0) {
708
        cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) pygi_arg_cache_free);
709 710
        g_ptr_array_set_size (cache->args_cache, n_args);
    }
711

712
    if (!_args_cache_generate (callable_info, cache))
713 714
        goto err;

715
    return cache;
716
err:
717
    pygi_callable_cache_free (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
718
    return NULL;
719
}