pygi-cache.c 41.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* -*- Mode: C; c-basic-offset: 4 -*-
 * vim: tabstop=4 shiftwidth=4 expandtab
 *
 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA
 */
21

22 23
#include <girepository.h>

24
#include "pygi-info.h"
25
#include "pygi-cache.h"
26 27
#include "pygi-marshal-to-py.h"
#include "pygi-marshal-from-py.h"
28
#include "pygi-marshal-cleanup.h"
29
#include "pygi-type.h"
30
#include "pygi-hashtable.h"
31
#include "pygi-basictype.h"
32
#include "pygi-list.h"
33

34 35

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
36
                                             GITypeInfo *type_info,
37 38
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
39
                                             PyGIDirection direction,
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
                                             /* will be removed */
                                             PyGICallableCache *callable_cache);


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


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)
{
    if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }

    g_base_info_ref ( (GIBaseInfo *)iface_info);
    iface_cache->interface_info = iface_info;
    iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE;

    return TRUE;
}

124

125
/* cleanup */
126
void
127
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
128 129 130 131
{
    if (cache == NULL)
        return;

132
    if (cache->type_info != NULL)
133
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
134
    if (cache->destroy_notify)
135
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
136
    else
137
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
138 139 140
}

static void
141
_interface_cache_free_func (PyGIInterfaceCache *cache)
142 143
{
    if (cache != NULL) {
144
        Py_XDECREF (cache->py_type);
145
        if (cache->type_name != NULL)
146
            g_free (cache->type_name);
147
        if (cache->interface_info != NULL)
148 149
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
150 151 152 153
    }
}


154
static void
155
_sequence_cache_free_func (PyGISequenceCache *cache)
156
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
157
    if (cache != NULL) {
158 159
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
160
    }
161 162
}

163 164 165 166 167 168 169 170 171
static void
_array_cache_free_func (PyGIArgGArray *cache)
{
    if (cache != NULL) {
        _pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
        g_slice_free (PyGIArgGArray, cache);
    }
}

172
static void
173
_callback_cache_free_func (PyGICallbackCache *cache)
174
{
175 176
    if (cache != NULL) {
        if (cache->interface_info != NULL)
177
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
178

179
        g_slice_free (PyGICallbackCache, cache);
180
    }
181 182 183
}

void
184
_pygi_callable_cache_free (PyGICallableCache *cache)
185
{
186 187 188
    if (cache == NULL)
        return;

189
    g_slist_free (cache->to_py_args);
190 191
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);
192
    g_ptr_array_unref (cache->args_cache);
193

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

197
    g_slice_free (PyGICallableCache, cache);
198 199 200 201
}

/* cache generation */

202 203
static PyGIInterfaceCache *
_interface_cache_new (GIInterfaceInfo *iface_info)
204 205
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
206

207 208
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
209
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
210
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
211 212 213 214

    if (ic->py_type == NULL)
        return NULL;

215
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
216 217 218
    return ic;
}

219 220 221 222 223 224
gboolean
pygi_arg_sequence_setup (PyGISequenceCache  *sc,
                         GITypeInfo         *type_info,
                         GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                         GITransfer          transfer,
                         PyGIDirection       direction)
225 226
{
    GITypeInfo *item_type_info;
227
    GITransfer item_transfer;
228

229 230 231 232 233 234 235
    if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }
236

237
    sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
238
    item_type_info = g_type_info_get_param_type (type_info, 0);
239 240
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
241

242 243 244 245
    sc->item_cache = _arg_cache_new (item_type_info,
                                     NULL,
                                     item_transfer,
                                     direction,
246 247
                                     0, 0,
                                     NULL);
248

249 250
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

251
    if (sc->item_cache == NULL) {
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
        return FALSE;
    }

    return TRUE;
}

static gboolean
pygi_arg_garray_setup (PyGIArgGArray      *sc,
                       GITypeInfo         *type_info,
                       GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                       GITransfer          transfer,
                       PyGIDirection       direction,
                       gssize              child_offset)
{
    GITypeInfo *item_type_info;

    if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
                                  type_info,
                                  arg_info,
                                  transfer,
                                  direction)) {
        return FALSE;
274
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
275

276 277 278 279 280 281 282 283
    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
    sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
    sc->len_arg_index = g_type_info_get_array_length (type_info);
    if (sc->len_arg_index >= 0)
        sc->len_arg_index += child_offset;

    item_type_info = g_type_info_get_param_type (type_info, 0);
284 285
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
286

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
    return TRUE;
}

static PyGISequenceCache *
pygi_arg_sequence_new (GITypeInfo *type_info,
                       GIArgInfo *arg_info,
                       GITransfer transfer,
                       PyGIDirection direction)
{
    PyGISequenceCache *sc = g_slice_new0 (PyGISequenceCache);
    if (sc == NULL)
        return NULL;

    if (!pygi_arg_sequence_setup (sc, type_info, arg_info, transfer, direction)) {
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
        return NULL;
    }

305
    return sc;
306 307
}

308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
static PyGIArgGArray *
_arg_array_cache_new (GITypeInfo *type_info,
                      GIArgInfo *arg_info,
                      GITransfer transfer,
                      PyGIDirection direction,
                      gssize child_offset)
{
    PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
    if (array_cache == NULL)
        return NULL;

    if (!pygi_arg_garray_setup (array_cache,
                                type_info,
                                arg_info,
                                transfer,
                                direction,
                                child_offset)) {
        _pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
        return NULL;
    }

    return array_cache;
}

332 333 334 335
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
                     GIInterfaceInfo *iface_info,
                     gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
336 337 338
{
   PyGICallbackCache *cc;

339
   cc = g_slice_new0 (PyGICallbackCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
340 341
   ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

342
   cc->user_data_index = g_arg_info_get_closure (arg_info);
343
   if (cc->user_data_index != -1)
344
       cc->user_data_index += child_offset;
345
   cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
346
   if (cc->destroy_notify_index != -1)
347
       cc->destroy_notify_index += child_offset;
348
   cc->scope = g_arg_info_get_scope (arg_info);
349 350
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
351 352 353
   return cc;
}

354
PyGIArgCache *
355
_arg_cache_alloc (void)
356
{
357
    return g_slice_new0 (PyGIArgCache);
358
}
359 360


361 362
static PyGIArgCache*
_arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
363
                                PyGICallableCache *callable_cache,
364
                                PyGIDirection direction,
365 366
                                gssize arg_index,
                                gssize *py_arg_index)
367
{
368
    PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
369
    if (seq_cache->len_arg_index >= 0) {
370
        PyGIArgCache *child_cache = NULL;
371

372 373
        child_cache = _pygi_callable_cache_get_arg (callable_cache,
                                                    seq_cache->len_arg_index);
374
        if (child_cache == NULL) {
375
            child_cache = _arg_cache_alloc ();
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
        } else {
            /* If the "length" arg cache already exists (the length comes before
             * the array in the argument list), remove it from the to_py_args list
             * because it does not belong in "to python" return tuple. The length
             * will implicitly be a part of the returned Python list.
             */
            if (direction & PYGI_DIRECTION_TO_PYTHON) {
                callable_cache->to_py_args =
                    g_slist_remove (callable_cache->to_py_args, child_cache);
            }

            /* This is a case where the arg cache already exists and has been
             * setup by another array argument sharing the same length argument.
             * See: gi_marshalling_tests_multi_array_key_value_in
             */
            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
                return child_cache;
393 394
        }

395 396 397 398 399
        /* There is a length argument for this array, so increment the number
         * of "to python" child arguments when applicable.
         */
        if (direction & PYGI_DIRECTION_TO_PYTHON)
             callable_cache->n_to_py_child_args++;
400

401
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
402
        child_cache->direction = direction;
403 404
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
405

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
        /* ugly edge case code:
         *
         * When the length comes before the array parameter we need to update
         * indexes of arguments after the index argument.
         */
        if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
            gssize i;
            (*py_arg_index) -= 1;
            callable_cache->n_py_args -= 1;

            for (i = seq_cache->len_arg_index + 1;
                   i < _pygi_callable_cache_args_len (callable_cache); i++) {
                PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
                if (update_cache == NULL)
                    break;

                update_cache->py_arg_index -= 1;
            }
        }

426
        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
427
        return child_cache;
428 429
    }

430 431
    return NULL;
}
432

433 434 435 436 437 438 439 440
static gboolean
_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                PyGICallableCache *callable_cache,
                                GITypeInfo *type_info,
                                GITransfer transfer,
                                PyGIDirection direction,
                                gssize arg_index)
{
441
    PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
442 443 444
    seq_cache->array_type = g_type_info_get_array_type (type_info);
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
445
    return TRUE;
446 447
}

448
static gboolean
449 450 451 452 453 454
_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                              PyGICallableCache *callable_cache,
                              GITypeInfo *type_info,
                              GITransfer transfer,
                              PyGIDirection direction,
                              gssize arg_index)
455
{
456
    PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
457
    seq_cache->array_type = g_type_info_get_array_type (type_info);
458 459
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
460 461 462
    return TRUE;
}

463
static void
464
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
465
{
466
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
467
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
468 469
}

470
static void
471
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
472
{
473
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
474
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
475 476
}

477
static void
478 479
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
480
{
481
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
482 483
}

484
static void
485 486
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
487
{
488
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
489 490
}

491
static void
492 493 494
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
495
{
496
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
497
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
498
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
499 500

    if (iface_cache->g_type == G_TYPE_VALUE)
501
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
502
    else if (iface_cache->is_foreign)
503
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
504
}
505

506
static void
507 508 509
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
510 511
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
512
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
513
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
514 515

    if (iface_cache->is_foreign)
516
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
517 518
}

519
static void
520 521
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
522
{
523 524
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
525 526
}

527
static void
528 529
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
530
{
531
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object_cache_adapter;
532
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
533 534
}

535
static void
536 537
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
538
{
539
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
540
    if (callback_cache->user_data_index >= 0) {
541
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
542
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
543
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
544
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
545 546
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->user_data_index,
                                      user_data_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
547
    }
548 549

    if (callback_cache->destroy_notify_index >= 0) {
550
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
551
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
552
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
553 554
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
                                      destroy_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
555
    }
556
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
557
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
558 559
}

560
static void
561
_arg_cache_to_py_interface_callback_setup (void)
562
{
563 564 565
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
566

567
static void
568 569
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
570
{
571
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
572 573
}

574
static void
575 576
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
577
{
578
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
579
}
580

581
static void
582 583
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
584
{
585
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
586 587
}

588
static void
589 590
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
591
{
592
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
593 594
}

595

596
PyGIArgCache *
597 598 599 600 601 602
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
603
{
604
    PyGIArgCache *arg_cache = NULL;
605
    gssize child_offset = 0;
606
    GIInfoType info_type;
607 608 609 610 611

    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                 callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
612

613 614
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

615
    /* Callbacks are special cased */
616 617
    if (info_type == GI_INFO_TYPE_CALLBACK) {
        PyGICallbackCache *callback_cache;
618

619 620 621 622 623 624 625 626 627 628 629
        if (direction & PYGI_DIRECTION_TO_PYTHON) {
            _arg_cache_to_py_interface_callback_setup ();
            return NULL;
        }

        callback_cache =
            _callback_cache_new (arg_info,
                                 iface_info,
                                 child_offset);

        arg_cache = (PyGIArgCache *)callback_cache;
630 631
        if (arg_cache == NULL)
            return NULL;
632 633 634 635 636 637 638 639 640 641 642 643

        pygi_arg_base_setup (arg_cache,
                             type_info,
                             arg_info,
                             transfer,
                             direction);

        if (direction & PYGI_DIRECTION_FROM_PYTHON)
            _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);

        return arg_cache;

644 645
    }

646 647 648 649
    arg_cache = (PyGIArgCache *)_interface_cache_new (iface_info);
    if (arg_cache == NULL)
        return NULL;

650 651
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
652
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
653
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
654

655
            if (direction & PYGI_DIRECTION_TO_PYTHON)
656
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
657

658
            break;
659
        case GI_INFO_TYPE_BOXED:
660
        case GI_INFO_TYPE_STRUCT:
661
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
662 663 664 665
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

666
            if (direction & PYGI_DIRECTION_TO_PYTHON)
667 668 669
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
670 671 672
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
673
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
674
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
675

676
            if (direction & PYGI_DIRECTION_TO_PYTHON)
677
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
678

679 680
            break;
        case GI_INFO_TYPE_ENUM:
681
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
682
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
683

684
            if (direction & PYGI_DIRECTION_TO_PYTHON)
685
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
686

687 688
            break;
        case GI_INFO_TYPE_FLAGS:
689
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
690
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
691

692
            if (direction & PYGI_DIRECTION_TO_PYTHON)
693
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
694

695 696
            break;
        default:
697
            g_assert_not_reached ();
698 699
    }

700 701 702 703 704 705
    pygi_arg_interface_setup ((PyGIInterfaceCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction,
                              iface_info);
706 707

    return arg_cache;
708 709
}

710
PyGIArgCache *
711
_arg_cache_new (GITypeInfo *type_info,
712
                GIArgInfo *arg_info,     /* may be null */
713
                GITransfer transfer,
714
                PyGIDirection direction,
715
                gssize c_arg_index,
716 717
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
718
{
719
    PyGIArgCache *arg_cache = NULL;
720
    gssize child_offset = 0;
721
    GITypeTag type_tag;
722

723 724
    type_tag = g_type_info_get_tag (type_info);

725 726 727 728
    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
729

730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
    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:
746
       case GI_TYPE_TAG_FILENAME:
747 748 749 750 751 752 753 754
           arg_cache = pygi_arg_basic_type_new_from_info (type_info, arg_info, transfer, direction);
           if (arg_cache) {
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
           } else {
               return NULL;
           }
755

756 757
       case GI_TYPE_TAG_ARRAY:
           {
758 759 760 761 762 763
               PyGIArgGArray *seq_cache =
                   _arg_array_cache_new (type_info,
                                         arg_info,
                                         transfer,
                                         direction,
                                         child_offset);
764 765 766 767 768

               arg_cache = (PyGIArgCache *)seq_cache;
               if (arg_cache == NULL)
                   break;

769
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
770 771 772 773
                   _arg_cache_from_py_array_setup (arg_cache,
                                                   callable_cache,
                                                   type_info,
                                                   transfer,
774 775
                                                   direction,
                                                   c_arg_index);
776

777
               if (direction & PYGI_DIRECTION_TO_PYTHON)
778 779 780 781 782 783
                   _arg_cache_to_py_array_setup (arg_cache,
                                                 callable_cache,
                                                 type_info,
                                                 transfer,
                                                 direction,
                                                 c_arg_index);
784

785 786 787 788 789
               _arg_cache_array_len_arg_setup (arg_cache,
                                               callable_cache,
                                               direction,
                                               c_arg_index,
                                               &py_arg_index);
790

791 792 793
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
794 795 796
           }
       case GI_TYPE_TAG_GLIST:
           {
797 798 799 800
               arg_cache = pygi_arg_glist_new_from_info (type_info,
                                                         arg_info,
                                                         transfer,
                                                         direction);
801
               if (arg_cache == NULL)
802
                   return NULL;
803

804 805 806
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
807 808
           }
       case GI_TYPE_TAG_GSLIST:
809
           {
810 811 812 813
               arg_cache = pygi_arg_gslist_new_from_info (type_info,
                                                          arg_info,
                                                          transfer,
                                                          direction);
814
               if (arg_cache == NULL)
815
                   return NULL;
816

817 818 819
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
820
            }
821
       case GI_TYPE_TAG_GHASH:
822 823 824 825
           arg_cache = pygi_arg_hash_table_new_from_info (type_info, arg_info, transfer, direction);
           arg_cache->py_arg_index = py_arg_index;
           arg_cache->c_arg_index = c_arg_index;
           return arg_cache;
826

827
       case GI_TYPE_TAG_INTERFACE:
828
           {
829
               GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
830
               arg_cache = _arg_cache_new_for_interface (interface_info,
831
                                                         type_info,
832 833 834
                                                         arg_info,
                                                         transfer,
                                                         direction,
835
                                                         callable_cache);
836 837

               g_base_info_unref ( (GIBaseInfo *)interface_info);
838 839 840
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
841
           }
842
       case GI_TYPE_TAG_ERROR:
843
           arg_cache = _arg_cache_alloc ();
844 845 846
           if (arg_cache == NULL)
               break;

847
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
848
               _arg_cache_from_py_gerror_setup (arg_cache);
849

850
           if (direction & PYGI_DIRECTION_TO_PYTHON)
851
               _arg_cache_to_py_gerror_setup (arg_cache);
852

853 854 855
           break;
    }

856
    if (arg_cache != NULL) {
857
        pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction);
858 859 860 861 862
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
863 864
}

865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
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;
    }
}

882 883
/* Generate the cache for the callable's arguments */
static gboolean