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

#include "pygi-info.h"
23
#include "pygi-cache.h"
24
#include "pygi-marshal.h"
25
#include "pygi-marshal-cleanup.h"
26
#include "pygi-type.h"
27
#include <girepository.h>
28

29
PyGIArgCache * _arg_cache_new_from_type_info (GITypeInfo *type_info,
30
                                              PyGICallableCache *callable_cache,
31 32 33 34
                                              GIArgInfo *arg_info,
                                              GITypeTag type_tag,
                                              GITransfer transfer,
                                              GIDirection direction,
35 36
                                              gssize c_arg_index,
                                              gssize py_arg_index);
37

38
/* cleanup */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
39
void
40
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
41 42 43 44
{
    if (cache == NULL)
        return;

45
    if (cache->type_info != NULL)
46
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
47
    if (cache->destroy_notify)
48
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
49
    else
50
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
51 52 53
}

static void
54
_interface_cache_free_func (PyGIInterfaceCache *cache)
55 56
{
    if (cache != NULL) {
57
        Py_XDECREF (cache->py_type);
58
        if (cache->type_name != NULL)
59
            g_free (cache->type_name);
60
        if (cache->interface_info != NULL)
61 62
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
63 64 65
    }
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
66
static void
67
_hash_cache_free_func (PyGIHashCache *cache)
68
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
69
    if (cache != NULL) {
70 71 72
        _pygi_arg_cache_free (cache->key_cache);
        _pygi_arg_cache_free (cache->value_cache);
        g_slice_free (PyGIHashCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
73
    }
74 75
}

76
static void
77
_sequence_cache_free_func (PyGISequenceCache *cache)
78
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
79
    if (cache != NULL) {
80 81
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
82
    }
83 84
}

85
static void
86
_callback_cache_free_func (PyGICallbackCache *cache)
87
{
88 89
    if (cache != NULL) {
        if (cache->interface_info != NULL)
90
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
91

92
        g_slice_free (PyGICallbackCache, cache);
93
    }
94 95 96
}

void
97
_pygi_callable_cache_free (PyGICallableCache *cache)
98
{
99
    gssize i;
100

101 102 103
    if (cache == NULL)
        return;

104
    g_slist_free (cache->out_args);
105 106
    for (i = 0; i < cache->n_args; i++) {
        PyGIArgCache *tmp = cache->args_cache[i];
107
        _pygi_arg_cache_free (tmp);
108
    }
109
    if (cache->return_cache != NULL)
110
        _pygi_arg_cache_free (cache->return_cache);
111

112 113
    g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
    g_slice_free (PyGICallableCache, cache);
114 115 116 117
}

/* cache generation */

118
static inline PyGIInterfaceCache *
119
_interface_cache_new_from_interface_info (GIInterfaceInfo *iface_info)
120 121
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
122

123 124
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
125
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
126
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
127 128 129 130

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

131
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
132 133 134
    return ic;
}

135
static inline PyGISequenceCache *
136 137 138
_sequence_cache_new_from_type_info (GITypeInfo *type_info,
                                    GIDirection direction,
                                    GITransfer transfer,
139
                                    gssize child_offset)
140 141 142
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
143
    GITypeTag item_type_tag;
144
    GITransfer item_transfer;
145

146 147
    sc = g_slice_new0 (PyGISequenceCache);
    ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
148 149 150

    sc->fixed_size = -1;
    sc->len_arg_index = -1;
151
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
152
    if (!sc->is_zero_terminated) {
153
        sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
154
        if (sc->fixed_size < 0)
155
            sc->len_arg_index = g_type_info_get_array_length (type_info) + child_offset;
156
    }
157

158
    item_type_info = g_type_info_get_param_type (type_info, 0);
159
    item_type_tag = g_type_info_get_tag (item_type_info);
160

161 162
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
163

164 165 166 167 168 169 170
    sc->item_cache = _arg_cache_new_from_type_info (item_type_info,
                                                    NULL,
                                                    NULL,
                                                    item_type_tag,
                                                    item_transfer,
                                                    direction,
                                                    0, 0);
171

172
    if (sc->item_cache == NULL) {
173
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
174 175
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
176

177
    sc->item_cache->type_tag = item_type_tag;
178 179
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
180

181
    return sc;
182
}
John (J5) Palmieri's avatar
John (J5) Palmieri committed
183
static inline PyGIHashCache *
184 185 186
_hash_cache_new_from_type_info (GITypeInfo *type_info,
                                GIDirection direction,
                                GITransfer transfer)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
187 188 189 190 191 192
{
    PyGIHashCache *hc;
    GITypeInfo *key_type_info;
    GITypeTag key_type_tag;
    GITypeInfo *value_type_info;
    GITypeTag value_type_tag;
193
    GITransfer item_transfer;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
194

195 196
    hc = g_slice_new0 (PyGIHashCache);
    ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
197 198 199 200 201
    key_type_info = g_type_info_get_param_type (type_info, 0);
    key_type_tag = g_type_info_get_tag (key_type_info);
    value_type_info = g_type_info_get_param_type (type_info, 1);
    value_type_tag = g_type_info_get_tag (value_type_info);

202 203
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
204

205 206 207 208 209 210 211
    hc->key_cache = _arg_cache_new_from_type_info (key_type_info,
                                                   NULL,
                                                   NULL,
                                                   key_type_tag,
                                                   item_transfer,
                                                   direction,
                                                   0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
212 213

    if (hc->key_cache == NULL) {
214
        _pygi_arg_cache_free ( (PyGIArgCache *)hc);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
215 216 217
        return NULL;
    }

218 219 220 221 222 223 224
    hc->value_cache = _arg_cache_new_from_type_info (value_type_info,
                                                     NULL,
                                                     NULL,
                                                     value_type_tag,
                                                     item_transfer,
                                                     direction,
                                                     0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
225 226

    if (hc->value_cache == NULL) {
227
        _pygi_arg_cache_free ( (PyGIArgCache *)hc);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
228 229 230 231 232 233 234 235 236 237 238
        return NULL;
    }

    hc->key_cache->type_tag = key_type_tag;
    hc->value_cache->type_tag = value_type_tag;

    g_base_info_unref( (GIBaseInfo *)key_type_info);
    g_base_info_unref( (GIBaseInfo *)value_type_info);

    return hc;
}
239

John (J5) Palmieri's avatar
John (J5) Palmieri committed
240
static inline PyGICallbackCache *
241 242
_callback_cache_new_from_arg_info (GIArgInfo *arg_info,
                                   GIInterfaceInfo *iface_info,
243
                                   gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
244 245 246
{
   PyGICallbackCache *cc;

247 248
   cc = g_slice_new0 (PyGICallbackCache);
   cc->user_data_index = g_arg_info_get_closure (arg_info);
249
   if (cc->user_data_index != -1)
250
       cc->user_data_index += child_offset;
251
   cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
252
   if (cc->destroy_notify_index != -1)
253
       cc->destroy_notify_index += child_offset;
254
   cc->scope = g_arg_info_get_scope (arg_info);
255 256
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
257 258 259
   return cc;
}

260
static inline PyGIArgCache *
261
_arg_cache_new (void)
262
{
263
    return g_slice_new0 (PyGIArgCache);
264
}
265

John (J5) Palmieri's avatar
John (J5) Palmieri committed
266
static inline void
267
_arg_cache_in_void_setup (PyGIArgCache *arg_cache)
268
{
269 270
    arg_cache->in_marshaller = _pygi_marshal_in_void;
}
271

John (J5) Palmieri's avatar
John (J5) Palmieri committed
272
static inline void
273
_arg_cache_out_void_setup (PyGIArgCache *arg_cache)
274 275
{
    arg_cache->out_marshaller = _pygi_marshal_out_void;
276 277
}

278
static inline void
279
_arg_cache_in_boolean_setup (PyGIArgCache *arg_cache)
280
{
281
    arg_cache->in_marshaller = _pygi_marshal_in_boolean;
282 283
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
284
static inline void
285
_arg_cache_out_boolean_setup (PyGIArgCache *arg_cache)
286 287 288 289 290
{
    arg_cache->out_marshaller = _pygi_marshal_out_boolean;
}

static inline void
291
_arg_cache_in_int8_setup (PyGIArgCache *arg_cache)
292
{
293
    arg_cache->in_marshaller = _pygi_marshal_in_int8;
294 295
}

296
static inline void
297
_arg_cache_out_int8_setup (PyGIArgCache *arg_cache)
298 299 300 301 302
{
    arg_cache->out_marshaller = _pygi_marshal_out_int8;
}

static inline void
303
_arg_cache_in_uint8_setup (PyGIArgCache *arg_cache)
304
{
305
    arg_cache->in_marshaller = _pygi_marshal_in_uint8;
306 307
}

308
static inline void
309
_arg_cache_out_uint8_setup (PyGIArgCache *arg_cache)
310 311 312 313 314
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint8;
}

static inline void
315
_arg_cache_in_int16_setup (PyGIArgCache *arg_cache)
316
{
317
    arg_cache->in_marshaller = _pygi_marshal_in_int16;
318 319
}

320
static inline void
321
_arg_cache_out_int16_setup (PyGIArgCache *arg_cache)
322 323 324 325 326
{
    arg_cache->out_marshaller = _pygi_marshal_out_int16;
}

static inline void
327
_arg_cache_in_uint16_setup (PyGIArgCache *arg_cache)
328
{
329
    arg_cache->in_marshaller = _pygi_marshal_in_uint16;
330 331
}

332
static inline void
333
_arg_cache_out_uint16_setup (PyGIArgCache *arg_cache)
334 335 336 337 338
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint16;
}

static inline void
339
_arg_cache_in_int32_setup (PyGIArgCache *arg_cache)
340
{
341
    arg_cache->in_marshaller = _pygi_marshal_in_int32;
342 343
}

344
static inline void
345
_arg_cache_out_int32_setup (PyGIArgCache *arg_cache)
346 347 348 349 350
{
    arg_cache->out_marshaller = _pygi_marshal_out_int32;
}

static inline void
351
_arg_cache_in_uint32_setup (PyGIArgCache *arg_cache)
352
{
353
    arg_cache->in_marshaller = _pygi_marshal_in_uint32;
354 355
}

356
static inline void
357
_arg_cache_out_uint32_setup (PyGIArgCache *arg_cache)
358 359 360 361 362
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint32;
}

static inline void
363
_arg_cache_in_int64_setup (PyGIArgCache *arg_cache)
364
{
365
    arg_cache->in_marshaller = _pygi_marshal_in_int64;
366 367
}

368
static inline void
369
_arg_cache_out_int64_setup (PyGIArgCache *arg_cache)
370 371 372 373 374
{
    arg_cache->out_marshaller = _pygi_marshal_out_int64;
}

static inline void
375
_arg_cache_in_uint64_setup (PyGIArgCache *arg_cache)
376
{
377
    arg_cache->in_marshaller = _pygi_marshal_in_uint64;
378 379
}

380
static inline void
381
_arg_cache_out_uint64_setup (PyGIArgCache *arg_cache)
382 383 384 385 386
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint64;
}

static inline void
387
_arg_cache_in_float_setup (PyGIArgCache *arg_cache)
388
{
389
    arg_cache->in_marshaller = _pygi_marshal_in_float;
390 391
}

392
static inline void
393
_arg_cache_out_float_setup (PyGIArgCache *arg_cache)
394 395 396 397 398
{
    arg_cache->out_marshaller = _pygi_marshal_out_float;
}

static inline void
399
_arg_cache_in_double_setup (PyGIArgCache *arg_cache)
400
{
401
    arg_cache->in_marshaller = _pygi_marshal_in_double;
402 403
}

404
static inline void
405
_arg_cache_out_double_setup (PyGIArgCache *arg_cache)
406 407 408 409 410
{
    arg_cache->out_marshaller = _pygi_marshal_out_double;
}

static inline void
411
_arg_cache_in_unichar_setup (PyGIArgCache *arg_cache)
412
{
413
    arg_cache->in_marshaller = _pygi_marshal_in_unichar;
414 415
}

416
static inline void
417
_arg_cache_out_unichar_setup (PyGIArgCache *arg_cache)
418 419 420 421 422
{
    arg_cache->out_marshaller = _pygi_marshal_out_unichar;
}

static inline void
423
_arg_cache_in_gtype_setup (PyGIArgCache *arg_cache)
424
{
425
    arg_cache->in_marshaller = _pygi_marshal_in_gtype;
426 427
}

428
static inline void
429
_arg_cache_out_gtype_setup (PyGIArgCache *arg_cache)
430 431 432 433 434
{
    arg_cache->out_marshaller = _pygi_marshal_out_gtype;
}

static inline void
435 436
_arg_cache_in_utf8_setup (PyGIArgCache *arg_cache,
                          GITransfer transfer)
437
{
438
    arg_cache->in_marshaller = _pygi_marshal_in_utf8;
439
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_utf8;
440
}
441

442
static inline void
443 444
_arg_cache_out_utf8_setup (PyGIArgCache *arg_cache,
                           GITransfer transfer)
445 446
{
    arg_cache->out_marshaller = _pygi_marshal_out_utf8;
447
    arg_cache->out_cleanup = _pygi_marshal_cleanup_out_utf8;
448 449
}

450
static inline void
451 452
_arg_cache_in_filename_setup (PyGIArgCache *arg_cache,
                              GITransfer transfer)
453
{
454
    arg_cache->in_marshaller = _pygi_marshal_in_filename;
455
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_utf8;
456 457
}

458
static inline void
459 460
_arg_cache_out_filename_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
461
{
462
    arg_cache->out_marshaller = _pygi_marshal_out_filename;
463
    arg_cache->out_cleanup = _pygi_marshal_cleanup_out_utf8;
464
}
465

466
static inline gboolean
467 468 469 470 471
_arg_cache_in_array_setup (PyGIArgCache *arg_cache,
                           PyGICallableCache *callable_cache,
                           GITypeInfo *type_info,
                           GITransfer transfer,
                           GIDirection direction)
472
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
473
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
474
    seq_cache->array_type = g_type_info_get_array_type (type_info);
475

476
    arg_cache->in_marshaller = _pygi_marshal_in_array;
477

478 479
    if (seq_cache->len_arg_index >= 0 &&
        direction == GI_DIRECTION_IN) {
480
        PyGIArgCache *child_cache = 
481
            callable_cache->args_cache[seq_cache->len_arg_index];
482

483 484 485
        if (child_cache == NULL) {
            child_cache = _arg_cache_new();
        } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD) {
486 487 488
            return TRUE;
        }

489 490 491 492
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
        child_cache->direction = direction;
        child_cache->in_marshaller = NULL;
        child_cache->out_marshaller = NULL;
493

494
        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
495 496
    }

497
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_array;
498 499

    return TRUE;
500 501
}

502
static inline gboolean
503 504 505 506 507 508
_arg_cache_out_array_setup (PyGIArgCache *arg_cache,
                            PyGICallableCache *callable_cache,
                            GITypeInfo *type_info,
                            GITransfer transfer,
                            GIDirection direction,
                            gssize arg_index)
509
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
510
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
511
    arg_cache->out_marshaller = _pygi_marshal_out_array;
512
    arg_cache->out_cleanup = _pygi_marshal_cleanup_out_array;
513

514
    seq_cache->array_type = g_type_info_get_array_type (type_info);
515 516

    if (seq_cache->len_arg_index >= 0) {
517
        PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
518
        if (seq_cache->len_arg_index < arg_index)
519
             callable_cache->n_out_child_args++;
520

521 522
        if (child_cache != NULL) {
            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
523 524
                return TRUE;

525
            callable_cache->out_args = 
526
                g_slist_remove (callable_cache->out_args, child_cache);
527
        } else {
528
            child_cache = _arg_cache_new ();
529
        }
530

531 532 533 534
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
        child_cache->direction = direction;
        child_cache->in_marshaller = NULL;
        child_cache->out_marshaller = NULL;
535

536
        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
537 538 539 540 541 542
    }

    return TRUE;
}

static inline void
543 544
_arg_cache_in_glist_setup (PyGIArgCache *arg_cache,
                           GITransfer transfer)
545
{
546
    arg_cache->in_marshaller = _pygi_marshal_in_glist;
547
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_glist;
548
}
549

550
static inline void
551 552
_arg_cache_out_glist_setup (PyGIArgCache *arg_cache,
                            GITransfer transfer)
553 554
{
    arg_cache->out_marshaller = _pygi_marshal_out_glist;
555
    arg_cache->in_cleanup = _pygi_marshal_cleanup_out_glist;
556 557
}

558
static inline void
559 560
_arg_cache_in_gslist_setup (PyGIArgCache *arg_cache,
                            GITransfer transfer)
561
{
562
    arg_cache->in_marshaller = _pygi_marshal_in_gslist;
563
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_glist;
564
}
565

566
static inline void
567 568
_arg_cache_out_gslist_setup (PyGIArgCache *arg_cache,
                             GITransfer transfer)
569 570
{
    arg_cache->out_marshaller = _pygi_marshal_out_gslist;
571
    arg_cache->out_cleanup = _pygi_marshal_cleanup_out_glist;
572 573
}

574
static inline void
575
_arg_cache_in_ghash_setup (PyGIArgCache *arg_cache)
576
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
577
    arg_cache->in_marshaller = _pygi_marshal_in_ghash;
578
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_ghash;
579 580
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
581
static inline void
582
_arg_cache_out_ghash_setup (PyGIArgCache *arg_cache)
583
{
584
    arg_cache->out_marshaller = _pygi_marshal_out_ghash;
585
    arg_cache->out_cleanup = _pygi_marshal_cleanup_out_ghash;
586 587 588
}

static inline void
589
_arg_cache_in_gerror_setup (PyGIArgCache *arg_cache)
590
{
591
    arg_cache->in_marshaller = _pygi_marshal_in_gerror;
592
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
593 594
}

595
static inline void
596
_arg_cache_out_gerror_setup (PyGIArgCache *arg_cache)
597 598
{
    arg_cache->out_marshaller = _pygi_marshal_out_gerror;
599
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
600 601 602
}

static inline void
603 604
_arg_cache_in_interface_union_setup (PyGIArgCache *arg_cache,
                                     GITransfer transfer)
605
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
606
    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
607 608 609
}

static inline void
610 611
_arg_cache_out_interface_union_setup (PyGIArgCache *arg_cache,
                                      GITransfer transfer)
612 613
{
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
614 615
}

616
static inline void
617 618 619
_arg_cache_in_interface_struct_setup (PyGIArgCache *arg_cache,
                                      GIInterfaceInfo *iface_info,
                                      GITransfer transfer)
620
{
621
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
622
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
623
    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
624 625

    if (iface_cache->g_type == G_TYPE_VALUE)
626 627 628
        arg_cache->in_cleanup = _pygi_marshal_cleanup_in_interface_struct_gvalue;
    else if (iface_cache->is_foreign)
        arg_cache->in_cleanup = _pygi_marshal_cleanup_in_interface_struct_foreign;
629
}
630

631
static inline void
632 633 634
_arg_cache_out_interface_struct_setup (PyGIArgCache *arg_cache,
                                       GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
635 636
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
637
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
638
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
639 640 641

    if (iface_cache->is_foreign)
        arg_cache->in_cleanup = _pygi_marshal_cleanup_out_interface_struct_foreign;
642 643
}

644
static inline void
645 646
_arg_cache_in_interface_object_setup (PyGIArgCache *arg_cache,
                                      GITransfer transfer)
647 648
{
    arg_cache->in_marshaller = _pygi_marshal_in_interface_object;
649
    arg_cache->in_cleanup = _pygi_marshal_cleanup_in_interface_object;
650 651
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
652
static inline void
653 654
_arg_cache_out_interface_object_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
655
{
656
    arg_cache->out_marshaller = _pygi_marshal_out_interface_object;
657
    arg_cache->out_cleanup = _pygi_marshal_cleanup_out_interface_object;
658 659 660
}

static inline void
661 662
_arg_cache_in_interface_callback_setup (PyGIArgCache *arg_cache,
                                        PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
663
{
664
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
665
    if (callback_cache->user_data_index >= 0) {
666
        PyGIArgCache *user_data_arg_cache = _arg_cache_new ();
667
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
668
        callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
669
    }
670 671

    if (callback_cache->destroy_notify_index >= 0) {
672
        PyGIArgCache *destroy_arg_cache = _arg_cache_new ();
673
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
674
        callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
675 676
    }
    arg_cache->in_marshaller = _pygi_marshal_in_interface_callback;
677 678
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
679
static inline void
680
_arg_cache_out_interface_callback_setup (void)
681
{
682 683 684
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
685

John (J5) Palmieri's avatar
John (J5) Palmieri committed
686
static inline void
687 688
_arg_cache_in_interface_enum_setup (PyGIArgCache *arg_cache,
                                    GITransfer transfer)
689
{
690
    arg_cache->in_marshaller = _pygi_marshal_in_interface_enum;
691 692
}

693
static inline void
694 695
_arg_cache_out_interface_enum_setup (PyGIArgCache *arg_cache,
                                     GITransfer transfer)
696
{
697 698
    arg_cache->out_marshaller = _pygi_marshal_out_interface_enum;
}
699

John (J5) Palmieri's avatar
John (J5) Palmieri committed
700
static inline void
701 702
_arg_cache_in_interface_flags_setup (PyGIArgCache *arg_cache,
                                     GITransfer transfer)
703
{
704
    arg_cache->in_marshaller = _pygi_marshal_in_interface_flags;
705 706
}

707
static inline void
708 709
_arg_cache_out_interface_flags_setup (PyGIArgCache *arg_cache,
                                      GITransfer transfer)
710
{
711 712 713 714 715
    arg_cache->out_marshaller = _pygi_marshal_out_interface_flags;
}

static inline PyGIArgCache *
_arg_cache_new_from_interface_info (GIInterfaceInfo *iface_info,
716
                                    PyGICallableCache *callable_cache,
717 718 719 720
                                    GIArgInfo *arg_info,
                                    GIInfoType info_type,
                                    GITransfer transfer,
                                    GIDirection direction,
721 722
                                    gssize c_arg_index,
                                    gssize py_arg_index)
723 724
{
    PyGIInterfaceCache *iface_cache = NULL;