pygi-cache.c 45.6 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 25
#include "pygi-marshal-to-py.h"
#include "pygi-marshal-from-py.h"
26
#include "pygi-marshal-cleanup.h"
27
#include "pygi-type.h"
28
#include <girepository.h>
29

30 31 32 33
PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
                               PyGICallableCache *callable_cache,
                               GIArgInfo *arg_info,
                               GITransfer transfer,
34
                               PyGIDirection direction,
35 36 37 38 39 40 41
                               gssize c_arg_index,
                               gssize py_arg_index);

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                                             PyGICallableCache *callable_cache,
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
42
                                             PyGIDirection direction,
43 44
                                             gssize c_arg_index,
                                             gssize py_arg_index);
45
/* cleanup */
Martin Pitt's avatar
Martin Pitt committed
46
static void
47
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
48 49 50 51
{
    if (cache == NULL)
        return;

52
    if (cache->type_info != NULL)
53
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
54
    if (cache->destroy_notify)
55
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
56
    else
57
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
58 59 60
}

static void
61
_interface_cache_free_func (PyGIInterfaceCache *cache)
62 63
{
    if (cache != NULL) {
64
        Py_XDECREF (cache->py_type);
65
        if (cache->type_name != NULL)
66
            g_free (cache->type_name);
67
        if (cache->interface_info != NULL)
68 69
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
70 71 72
    }
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
73
static void
74
_hash_cache_free_func (PyGIHashCache *cache)
75
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
76
    if (cache != NULL) {
77 78 79
        _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
80
    }
81 82
}

83
static void
84
_sequence_cache_free_func (PyGISequenceCache *cache)
85
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
86
    if (cache != NULL) {
87 88
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
89
    }
90 91
}

92
static void
93
_callback_cache_free_func (PyGICallbackCache *cache)
94
{
95 96
    if (cache != NULL) {
        if (cache->interface_info != NULL)
97
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
98

99
        g_slice_free (PyGICallbackCache, cache);
100
    }
101 102 103
}

void
104
_pygi_callable_cache_free (PyGICallableCache *cache)
105
{
106
    gssize i;
107

108 109 110
    if (cache == NULL)
        return;

111
    g_slist_free (cache->to_py_args);
112 113 114
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);

115 116
    for (i = 0; i < cache->n_args; i++) {
        PyGIArgCache *tmp = cache->args_cache[i];
117
        _pygi_arg_cache_free (tmp);
118
    }
119
    if (cache->return_cache != NULL)
120
        _pygi_arg_cache_free (cache->return_cache);
121

122 123
    g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
    g_slice_free (PyGICallableCache, cache);
124 125 126 127
}

/* cache generation */

128 129
static PyGIInterfaceCache *
_interface_cache_new (GIInterfaceInfo *iface_info)
130 131
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
132

133 134
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
135
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
136
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
137 138 139 140

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

141
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
142 143 144
    return ic;
}

145 146 147 148 149
static PyGISequenceCache *
_sequence_cache_new (GITypeInfo *type_info,
                     GIDirection direction,
                     GITransfer transfer,
                     gssize child_offset)
150 151 152
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
153
    GITransfer item_transfer;
154

155 156
    sc = g_slice_new0 (PyGISequenceCache);
    ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
157

158
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
159 160 161 162
    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;
163

164 165
    item_type_info = g_type_info_get_param_type (type_info, 0);

166 167
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
168

169 170 171 172 173 174
    sc->item_cache = _arg_cache_new (item_type_info,
                                     NULL,
                                     NULL,
                                     item_transfer,
                                     direction,
                                     0, 0);
175

176
    if (sc->item_cache == NULL) {
177
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
178 179
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
180

181 182
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
183

184
    return sc;
185
}
186 187 188 189
static PyGIHashCache *
_hash_cache_new (GITypeInfo *type_info,
                 GIDirection direction,
                 GITransfer transfer)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
190 191 192 193
{
    PyGIHashCache *hc;
    GITypeInfo *key_type_info;
    GITypeInfo *value_type_info;
194
    GITransfer item_transfer;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
195

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

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

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

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

216 217 218 219 220 221
    hc->value_cache = _arg_cache_new (value_type_info,
                                      NULL,
                                      NULL,
                                      item_transfer,
                                      direction,
                                      0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
222 223

    if (hc->value_cache == NULL) {
224
        _pygi_arg_cache_free ( (PyGIArgCache *)hc);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
225 226 227 228 229 230 231 232
        return NULL;
    }

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

    return hc;
}
233

234 235 236 237
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
                     GIInterfaceInfo *iface_info,
                     gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
238 239 240
{
   PyGICallbackCache *cc;

241
   cc = g_slice_new0 (PyGICallbackCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
242 243
   ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

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

256 257
static PyGIArgCache *
_arg_cache_alloc (void)
258
{
259
    return g_slice_new0 (PyGIArgCache);
260
}
261

262 263 264 265 266 267
static void
_arg_cache_from_py_basic_type_setup (PyGIArgCache *arg_cache)
{
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
}

268 269 270 271 272 273
static void
_arg_cache_to_py_basic_type_setup (PyGIArgCache *arg_cache)
{
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type;
}

274
static void
275
_arg_cache_from_py_void_setup (PyGIArgCache *arg_cache)
276
{
277
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_void;
278
}
279

280
static void
281
_arg_cache_to_py_void_setup (PyGIArgCache *arg_cache)
282
{
283
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_void;
284 285
}

286
static void
287
_arg_cache_from_py_float_setup (PyGIArgCache *arg_cache)
288
{
289
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_float;
290 291
}

292
static void
293
_arg_cache_from_py_double_setup (PyGIArgCache *arg_cache)
294
{
295
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_double;
296 297
}

298
static void
299
_arg_cache_from_py_unichar_setup (PyGIArgCache *arg_cache)
300
{
301
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_unichar;
302 303
}

304
static void
305
_arg_cache_from_py_gtype_setup (PyGIArgCache *arg_cache)
306
{
307
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gtype;
308 309
}

310
static void
311 312
_arg_cache_from_py_utf8_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
313
{
314 315
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_utf8;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
316
}
317

318
static void
319 320
_arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
321
{
322
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type;
323
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
324 325
}

326
static void
327 328
_arg_cache_from_py_filename_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
329
{
330 331
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_filename;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
332 333
}

334
static void
335 336
_arg_cache_to_py_filename_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
337
{
338
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type;
339
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
340
}
341

342
static gboolean
343 344 345 346
_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                PyGICallableCache *callable_cache,
                                GITypeInfo *type_info,
                                GITransfer transfer,
347 348
                                PyGIDirection direction,
                                gssize arg_index)
349
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
350
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
351
    seq_cache->array_type = g_type_info_get_array_type (type_info);
352

353
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
354

355
    if (seq_cache->len_arg_index >= 0) {
356
        PyGIArgCache *child_cache = 
357
            callable_cache->args_cache[seq_cache->len_arg_index];
358

359
        if (child_cache == NULL) {
360
            child_cache = _arg_cache_alloc ();
361 362
        } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
                   child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
363
            arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
364 365 366
            return TRUE;
        }

367 368 369 370 371
        if (seq_cache->len_arg_index < arg_index)
            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE;
        else
            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;

372
        child_cache->direction = direction;
373 374
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
375

376
        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
377 378
    }

379
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
380 381

    return TRUE;
382 383
}

384
static gboolean
385 386 387 388 389 390
_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                              PyGICallableCache *callable_cache,
                              GITypeInfo *type_info,
                              GITransfer transfer,
                              PyGIDirection direction,
                              gssize arg_index)
391
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
392
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
393 394
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
395

396
    seq_cache->array_type = g_type_info_get_array_type (type_info);
397 398

    if (seq_cache->len_arg_index >= 0) {
399
        PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
400
        if (seq_cache->len_arg_index < arg_index)
401
             callable_cache->n_to_py_child_args++;
402

403
        if (child_cache != NULL) {
404 405
            callable_cache->to_py_args =
                g_slist_remove (callable_cache->to_py_args, child_cache);
406 407 408 409

            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
                child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE)
                return TRUE;
410
        } else {
411
            child_cache = _arg_cache_alloc ();
412
        }
413

414 415
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
        child_cache->direction = direction;
416 417
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
418

419
        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
420 421 422 423 424
    }

    return TRUE;
}

425
static void
426 427
_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
                                GITransfer transfer)
428
{
429 430
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
431
}
432

433
static void
434 435
_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
                              GITransfer transfer)
436
{
437 438
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
439 440
}

441
static void
442 443
_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
444
{
445 446
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
447
}
448

449
static void
450 451
_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
452
{
453 454
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
455 456
}

457
static void
458
_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache)
459
{
460 461
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash;
462 463
}

464
static void
465
_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache)
466
{
467 468
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash;
469 470
}

471
static void
472
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
473
{
474
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
475
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
476 477
}

478
static void
479
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
480
{
481
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
482
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
483 484
}

485
static void
486 487
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
488
{
489
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct;
490 491
}

492
static void
493 494
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
495
{
496
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct;
497 498
}

499
static void
500 501 502
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
503
{
504
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
505
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
506
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct;
507 508

    if (iface_cache->g_type == G_TYPE_VALUE)
509
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
510
    else if (iface_cache->is_foreign)
511
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
512
}
513

514
static void
515 516 517
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
518 519
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
520
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
521
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct;
522 523

    if (iface_cache->is_foreign)
524
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
525 526
}

527
static void
528 529
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
530
{
531 532
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
533 534
}

535
static void
536 537
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
538
{
539 540
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
541 542
}

543
static void
544 545
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
546
{
547
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
548
    if (callback_cache->user_data_index >= 0) {
549
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
550
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
551
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
552
        callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
553
    }
554 555

    if (callback_cache->destroy_notify_index >= 0) {
556
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
557
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
558
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
559
        callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
560
    }
561
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
562
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
563 564
}

565
static void
566
_arg_cache_to_py_interface_callback_setup (void)
567
{
568 569 570
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
571

572
static void
573 574
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
575
{
576
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
577 578
}

579
static void
580 581
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
582
{
583
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
584
}
585

586
static void
587 588
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
589
{
590
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
591 592
}

593
static void
594 595
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
596
{
597
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
598 599
}

600 601 602 603 604
PyGIArgCache *
_arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                              PyGICallableCache *callable_cache,
                              GIArgInfo *arg_info,
                              GITransfer transfer,
605
                              PyGIDirection direction,
606 607
                              gssize c_arg_index,
                              gssize py_arg_index)
608 609
{
    PyGIInterfaceCache *iface_cache = NULL;
610
    PyGIArgCache *arg_cache = NULL;
611
    gssize child_offset = 0;
612
    GIInfoType info_type;
613 614 615 616 617

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

619 620
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

621 622
    /* Callbacks are special cased */
    if (info_type != GI_INFO_TYPE_CALLBACK) {
623
        iface_cache = _interface_cache_new (iface_info);
624 625 626 627 628 629

        arg_cache = (PyGIArgCache *)iface_cache;
        if (arg_cache == NULL)
            return NULL;
    }

630 631
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
632 633
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
634

635 636
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
637

638
            break;
639
        case GI_INFO_TYPE_BOXED:
640
        case GI_INFO_TYPE_STRUCT:
641 642 643 644 645 646 647 648 649
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
650 651 652
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
653 654
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
655

656 657
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
658

659 660
            break;
        case GI_INFO_TYPE_CALLBACK:
661 662 663
            {
                PyGICallbackCache *callback_cache;

664 665
                if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
                    _arg_cache_to_py_interface_callback_setup ();
666 667 668
                    return NULL;
                }

John (J5) Palmieri's avatar
John (J5) Palmieri committed
669
                callback_cache =
670 671 672
                    _callback_cache_new (arg_info,
                                         iface_info,
                                         child_offset);
673 674 675 676 677

                arg_cache = (PyGIArgCache *)callback_cache;
                if (arg_cache == NULL)
                    return NULL;

678 679
                if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
                    _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);
680 681 682

                break;
            }
683
        case GI_INFO_TYPE_ENUM:
684 685
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
686

687 688
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
689

690 691
            break;
        case GI_INFO_TYPE_FLAGS:
692 693
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
694

695 696
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
697

698 699
            break;
        default:
700
            g_assert_not_reached ();
701 702 703 704 705 706 707 708
    }

    if (arg_cache != NULL) {
        arg_cache->direction = direction;
        arg_cache->transfer = transfer;
        arg_cache->type_tag = GI_TYPE_TAG_INTERFACE;
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
709

710
        if (iface_cache != NULL) {
711
            g_base_info_ref ( (GIBaseInfo *)iface_info);
712 713
            iface_cache->interface_info = iface_info;
        }
714
    }
715 716

    return arg_cache;
717 718
}

719
PyGIArgCache *
720 721 722 723
_arg_cache_new (GITypeInfo *type_info,
                PyGICallableCache *callable_cache,
                GIArgInfo *arg_info,
                GITransfer transfer,
724
                PyGIDirection direction,
725 726
                gssize c_arg_index,
                gssize py_arg_index)
727
{
728
    PyGIArgCache *arg_cache = NULL;
729
    gssize child_offset = 0;