pygi-cache.c 47.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 24
#include "pygi-cache.h"
#include "pygi-argument.h"
25
#include "pygi-type.h"
26
#include <girepository.h>
27

28
PyGIArgCache * _arg_cache_in_new_from_type_info (GITypeInfo *type_info,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
29 30 31 32 33 34 35
                                                 GIArgInfo *arg_info,
                                                 PyGIFunctionCache *function_cache,
                                                 GITypeTag type_tag,
                                                 GITransfer transfer,
                                                 GIDirection direction,
                                                 gint c_arg_index,
                                                 gint py_arg_index);
36 37 38 39 40 41 42 43

PyGIArgCache * _arg_cache_out_new_from_type_info (GITypeInfo *type_info,
                                                  PyGIFunctionCache *function_cache,
                                                  GITypeTag type_tag,
                                                  GITransfer transfer,
                                                  GIDirection direction,
                                                  gboolean is_caller_allocates,
                                                  gint c_arg_index);
44
/* cleanup */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
45 46 47 48 49 50
void
_pygi_arg_cache_free(PyGIArgCache *cache)
{
    if (cache == NULL)
        return;

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

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

John (J5) Palmieri's avatar
John (J5) Palmieri committed
72 73
static void
_hash_cache_free_func(PyGIHashCache *cache)
74
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
75 76 77
    if (cache != NULL) {
        _pygi_arg_cache_free(cache->key_cache);
        _pygi_arg_cache_free(cache->value_cache);
78
        g_slice_free(PyGIHashCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
79
    }
80 81
}

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

91
static void
John (J5) Palmieri's avatar
John (J5) Palmieri committed
92
_callback_cache_free_func(PyGICallbackCache *cache)
93
{
94 95 96 97
    if (cache != NULL) {
        if (cache->interface_info != NULL)
            g_base_info_unref( (GIBaseInfo *)cache->interface_info);

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

void
John (J5) Palmieri's avatar
John (J5) Palmieri committed
103
_pygi_function_cache_free(PyGIFunctionCache *cache)
104 105 106
{
    int i;

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

110 111 112
    g_slist_free(cache->out_args);
    for (i = 0; i < cache->n_args; i++) {
        PyGIArgCache *tmp = cache->args_cache[i];
113
        _pygi_arg_cache_free(tmp);
114
    }
115 116 117
    if (cache->return_cache != NULL)
        _pygi_arg_cache_free(cache->return_cache);

118
    g_slice_free1(cache->n_args * sizeof(PyGIArgCache *), cache->args_cache);
119 120 121 122 123
    g_slice_free(PyGIFunctionCache, cache);
}

/* cache generation */
static inline PyGIFunctionCache *
124
_function_cache_new_from_function_info(GIFunctionInfo *function_info)
125 126 127 128 129
{
    PyGIFunctionCache *fc;
    GIFunctionInfoFlags flags;

    fc = g_slice_new0(PyGIFunctionCache);
130 131

    fc->name = g_base_info_get_name((GIBaseInfo *)function_info);
132 133 134
    flags = g_function_info_get_flags(function_info);
    fc->is_method = flags & GI_FUNCTION_IS_METHOD;
    fc->is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
135

136
    fc->n_args = g_callable_info_get_n_args ( (GICallableInfo *) function_info) + (fc->is_method ? 1: 0);
137 138
    if (fc->n_args > 0)
        fc->args_cache = g_slice_alloc0(fc->n_args * sizeof(PyGIArgCache *));
139 140 141 142

    return fc;
}

143 144 145 146
static inline PyGIInterfaceCache *
_interface_cache_new_from_interface_info(GIInterfaceInfo *iface_info)
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
147

148
    ic = g_slice_new0(PyGIInterfaceCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
149
    ((PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
150 151 152 153 154 155 156 157 158 159 160
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
    if (ic->g_type != G_TYPE_NONE) {
        ic->py_type = _pygi_type_get_from_g_type (ic->g_type);
    } else {
        /* FIXME: avoid passing GI infos to noncache API */
        ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
    }

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

161
    ic->type_name = _pygi_g_base_info_get_fullname(iface_info);
162 163 164
    return ic;
}

165
static inline PyGISequenceCache *
166
_sequence_cache_new_from_type_info(GITypeInfo *type_info,
167 168
                                   GIDirection direction,
                                   GITransfer transfer,
169
                                   gint aux_offset)
170 171 172
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
173
    GITypeTag item_type_tag;
174
    GITransfer item_transfer;
175 176

    sc = g_slice_new0(PyGISequenceCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
177
    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
178 179 180 181

    sc->fixed_size = -1;
    sc->len_arg_index = -1;
    sc->is_zero_terminated = g_type_info_is_zero_terminated(type_info);
182
    if (!sc->is_zero_terminated)
183 184
        sc->fixed_size = g_type_info_get_array_fixed_size(type_info);
    if (sc->fixed_size < 0)
185
        sc->len_arg_index = g_type_info_get_array_length (type_info) + aux_offset;
186

187
    item_type_info = g_type_info_get_param_type (type_info, 0);
188
    item_type_tag = g_type_info_get_tag (item_type_info);
189

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    item_transfer = GI_TRANSFER_NOTHING;
    if (transfer == GI_TRANSFER_EVERYTHING ||
        transfer == GI_TRANSFER_CONTAINER)
        item_transfer = GI_TRANSFER_EVERYTHING;

    /* FIXME: in/out */

    if (direction == GI_DIRECTION_IN)
        sc->item_cache = _arg_cache_in_new_from_type_info(item_type_info,
                                                          NULL,
                                                          NULL,
                                                          item_type_tag,
                                                          item_transfer,
                                                          direction,
                                                          0, 0);
    else
        sc->item_cache = _arg_cache_out_new_from_type_info(item_type_info,
                                                          NULL,
                                                          item_type_tag,
                                                          item_transfer,
                                                          direction,
                                                          FALSE,
                                                          0);

214

215 216 217 218
    if (sc->item_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)sc);
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
219

220
    sc->item_cache->type_tag = item_type_tag;
221
    sc->item_size = _pygi_g_type_info_size(item_type_info);
222
    g_base_info_unref( (GIBaseInfo *) item_type_info);
223

224
    return sc;
225
}
John (J5) Palmieri's avatar
John (J5) Palmieri committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
static inline PyGIHashCache *
_hash_cache_new_from_type_info(GITypeInfo *type_info)
{
    PyGIHashCache *hc;
    GITypeInfo *key_type_info;
    GITypeTag key_type_tag;
    GITypeInfo *value_type_info;
    GITypeTag value_type_tag;

    hc = g_slice_new0(PyGIHashCache);
    ((PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
    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);

    hc->key_cache = _arg_cache_in_new_from_type_info(key_type_info,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
243
                                                     NULL,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
244 245 246 247 248 249 250 251 252 253 254 255
                                                     NULL,
                                                     key_type_tag,
                                                     GI_TRANSFER_EVERYTHING,
                                                     GI_DIRECTION_IN,
                                                     0, 0);

    if (hc->key_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)hc);
        return NULL;
    }

    hc->value_cache = _arg_cache_in_new_from_type_info(value_type_info,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
256
                                                       NULL,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
                                                       NULL,
                                                       value_type_tag,
                                                       GI_TRANSFER_EVERYTHING,
                                                       GI_DIRECTION_IN,
                                                       0, 0);

    if (hc->value_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)hc);
        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;
}
276

John (J5) Palmieri's avatar
John (J5) Palmieri committed
277
static inline PyGICallbackCache *
278
_callback_cache_new_from_arg_info(GIArgInfo *arg_info,
279
                                  GIInterfaceInfo *iface_info,
280
                                  gint aux_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
281 282 283 284
{
   PyGICallbackCache *cc;

   cc = g_slice_new0(PyGICallbackCache);
285 286
   cc->user_data_index = g_arg_info_get_closure(arg_info) + aux_offset;
   cc->destroy_notify_index = g_arg_info_get_destroy(arg_info) + aux_offset;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
287
   cc->scope = g_arg_info_get_scope(arg_info);
288 289
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
290 291 292
   return cc;
}

293 294 295 296 297
static inline PyGIArgCache *
_arg_cache_new(void)
{
    return g_slice_new0(PyGIArgCache);
}
298 299
/* process in args */

300 301
static inline PyGIArgCache *
_arg_cache_new_for_in_void(void)
302
{
303
     PyGIArgCache *arg_cache = _arg_cache_new();
304
     arg_cache->in_marshaller = _pygi_marshal_in_void;
305

306
     return arg_cache;
307 308
}

309 310
static inline PyGIArgCache *
_arg_cache_new_for_in_boolean(void)
311
{
312
    PyGIArgCache *arg_cache = _arg_cache_new();
313
    arg_cache->in_marshaller = _pygi_marshal_in_boolean;
314
    return arg_cache;
315 316
}

317 318
static inline PyGIArgCache *
_arg_cache_new_for_in_int8(void)
319
{
320
    PyGIArgCache *arg_cache = _arg_cache_new();
321
    arg_cache->in_marshaller = _pygi_marshal_in_int8;
322
    return arg_cache;
323 324
}

325 326
static inline PyGIArgCache *
_arg_cache_new_for_in_uint8(void)
327
{
328
    PyGIArgCache *arg_cache = _arg_cache_new();
329
    arg_cache->in_marshaller = _pygi_marshal_in_uint8;
330
    return arg_cache;
331 332
}

333 334
static inline PyGIArgCache *
_arg_cache_new_for_in_int16(void)
335
{
336
    PyGIArgCache *arg_cache = _arg_cache_new();
337
    arg_cache->in_marshaller = _pygi_marshal_in_int16;
338
    return arg_cache;
339 340
}

341 342
static inline PyGIArgCache *
_arg_cache_new_for_in_uint16(void)
343
{
344
    PyGIArgCache *arg_cache = _arg_cache_new();
345
    arg_cache->in_marshaller = _pygi_marshal_in_uint16;
346
    return arg_cache;
347 348
}

349 350
static inline PyGIArgCache *
_arg_cache_new_for_in_int32(void)
351
{
352
    PyGIArgCache *arg_cache = _arg_cache_new();
353
    arg_cache->in_marshaller = _pygi_marshal_in_int32;
354
    return arg_cache;
355 356
}

357 358
static inline PyGIArgCache *
_arg_cache_new_for_in_uint32(void)
359
{
360
    PyGIArgCache *arg_cache = _arg_cache_new();
361
    arg_cache->in_marshaller = _pygi_marshal_in_uint32;
362
    return arg_cache;
363 364
}

365 366
static inline PyGIArgCache *
_arg_cache_new_for_in_int64(void)
367
{
368
    PyGIArgCache *arg_cache = _arg_cache_new();
369
    arg_cache->in_marshaller = _pygi_marshal_in_int64;
370
    return arg_cache;
371 372
}

373 374
static inline PyGIArgCache *
_arg_cache_new_for_in_uint64(void)
375
{
376
    PyGIArgCache *arg_cache = _arg_cache_new();
377
    arg_cache->in_marshaller = _pygi_marshal_in_uint64;
378
    return arg_cache;
379 380
}

381 382
static inline PyGIArgCache *
_arg_cache_new_for_in_float(void)
383
{
384
    PyGIArgCache *arg_cache = _arg_cache_new();
385
    arg_cache->in_marshaller = _pygi_marshal_in_float;
386
    return arg_cache;
387 388
}

389 390
static inline PyGIArgCache *
_arg_cache_new_for_in_double(void)
391
{
392
    PyGIArgCache *arg_cache = _arg_cache_new();
393
    arg_cache->in_marshaller = _pygi_marshal_in_double;
394
    return arg_cache;
395 396
}

397 398
static inline PyGIArgCache *
_arg_cache_new_for_in_unichar(void)
399
{
400
    PyGIArgCache *arg_cache = _arg_cache_new();
401
    arg_cache->in_marshaller = _pygi_marshal_in_unichar;
402
    return arg_cache;
403 404
}

405 406
static inline PyGIArgCache *
_arg_cache_new_for_in_gtype(void)
407
{
408
    PyGIArgCache *arg_cache = _arg_cache_new();
409
    arg_cache->in_marshaller = _pygi_marshal_in_gtype;
410
    return arg_cache;
411 412
}

413 414
static inline PyGIArgCache *
_arg_cache_new_for_in_utf8(GITransfer transfer)
415
{
416
    PyGIArgCache *arg_cache = _arg_cache_new();
417
    arg_cache->in_marshaller = _pygi_marshal_in_utf8;
418 419 420
    if (arg_cache->transfer == GI_TRANSFER_NOTHING)
        arg_cache->cleanup = g_free;

421
    return arg_cache;
422 423
}

424 425
static inline PyGIArgCache *
_arg_cache_new_for_in_filename(GITransfer transfer)
426
{
427
    PyGIArgCache *arg_cache = _arg_cache_new();
428
    arg_cache->in_marshaller = _pygi_marshal_in_filename;
429 430 431
    if (arg_cache->transfer == GI_TRANSFER_NOTHING)
        arg_cache->cleanup = g_free;

432
    return arg_cache;
433 434
}

435
static inline PyGIArgCache *
436 437
_arg_cache_new_for_in_array(PyGIFunctionCache *function_cache,
                            GITypeInfo *type_info,
438
                            GITransfer transfer)
439
{
440 441 442
    PyGISequenceCache *seq_cache = _sequence_cache_new_from_type_info(type_info,
                                                                      GI_DIRECTION_IN,
                                                                      transfer, 
443 444
                                                                      (function_cache->is_method ? 1: 0));

445 446
    PyGIArgCache *arg_cache = (PyGIArgCache *)seq_cache;

447 448
    seq_cache->array_type = g_type_info_get_array_type(type_info);

449 450
    if (seq_cache->len_arg_index >= 0) {
        PyGIArgCache *aux_cache = _arg_cache_new();
John (J5) Palmieri's avatar
John (J5) Palmieri committed
451
        aux_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
452 453 454 455 456 457 458 459 460
        if (function_cache->args_cache[seq_cache->len_arg_index] != NULL) {
            PyGIArgCache *invalid_cache = function_cache->args_cache[seq_cache->len_arg_index];
            arg_cache->c_arg_index = invalid_cache->c_arg_index;
            _pygi_arg_cache_free(invalid_cache);
        }

        function_cache->args_cache[seq_cache->len_arg_index] = aux_cache;
    }

461
    arg_cache->in_marshaller = _pygi_marshal_in_array;
462 463

    /* arg_cache->cleanup = _pygi_cleanup_array; */
464
    return arg_cache;
465 466
}

467 468
static inline PyGIArgCache *
_arg_cache_new_for_in_glist(GITypeInfo *type_info,
469
                            GITransfer transfer)
470
{
471
    PyGIArgCache *arg_cache =
472 473 474 475
        (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info,
                                                           GI_DIRECTION_IN,
                                                           transfer,
                                                           0);
476
    arg_cache->in_marshaller = _pygi_marshal_in_glist;
477 478
    /* arg_cache->cleanup = */

479
    return arg_cache;
480 481
}

482 483
static inline PyGIArgCache *
_arg_cache_new_for_in_gslist(GITypeInfo *type_info,
484
                             GITransfer transfer)
485
{
486
    PyGIArgCache *arg_cache =
487 488 489 490
        (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info,
                                                           GI_DIRECTION_IN,
                                                           transfer,
                                                           0);
491
    arg_cache->in_marshaller = _pygi_marshal_in_gslist;
492 493
    /* arg_cache->cleanup = */

494
    return arg_cache;
495 496
}

497 498
static inline PyGIArgCache *
_arg_cache_new_for_in_ghash(GITypeInfo *type_info)
499
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
500 501
    PyGIArgCache *arg_cache = (PyGIArgCache *)_hash_cache_new_from_type_info(type_info);
    arg_cache->in_marshaller = _pygi_marshal_in_ghash;
502
    return arg_cache;
503 504
}

505 506
static inline PyGIArgCache *
_arg_cache_new_for_in_gerror(void)
507
{
508
    PyGIArgCache *arg_cache = _arg_cache_new();
509
    arg_cache->in_marshaller = _pygi_marshal_in_gerror;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
510
    arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
511
    return arg_cache;
512 513
}

514
static inline PyGIArgCache *
John (J5) Palmieri's avatar
John (J5) Palmieri committed
515 516
_arg_cache_new_for_in_interface_union(GIInterfaceInfo *iface_info,
                                      GITransfer transfer)
517
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
518 519 520
    PyGIInterfaceCache *iface_cache = _interface_cache_new_from_interface_info(iface_info);
    PyGIArgCache *arg_cache = (PyGIArgCache *)iface_cache;
    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
521
    return arg_cache;
522 523
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
524
static void
525 526 527 528
_g_slice_free_gvalue_func(GValue *value) {
    g_slice_free(GValue, value);
}

529
static inline PyGIArgCache *
530 531
_arg_cache_new_for_in_interface_struct(GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
532
{
533
    PyGIInterfaceCache *iface_cache = _interface_cache_new_from_interface_info(iface_info);
534
    PyGIArgCache *arg_cache = (PyGIArgCache *)iface_cache;
535 536 537 538 539 540 541
    iface_cache->is_foreign = g_struct_info_is_foreign( (GIStructInfo*)iface_info);
    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
    if (iface_cache->g_type == G_TYPE_VALUE)
        arg_cache->cleanup = _g_slice_free_gvalue_func;
    if (iface_cache->g_type == G_TYPE_CLOSURE)
        arg_cache->cleanup = g_closure_unref;

542 543 544 545
    return arg_cache;
}

static inline PyGIArgCache *
546 547
_arg_cache_new_for_in_interface_object(GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
548
{
549
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
550 551 552 553 554 555 556 557
    arg_cache->in_marshaller = _pygi_marshal_in_interface_object;
    if (transfer == GI_TRANSFER_EVERYTHING)
        arg_cache->cleanup = (GDestroyNotify)g_object_unref;

    return arg_cache;
}

static inline PyGIArgCache *
558 559
_arg_cache_new_for_in_interface_boxed(GIInterfaceInfo *iface_info,
                                      GITransfer transfer)
560
{
561 562
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
    arg_cache->in_marshaller = _pygi_marshal_in_interface_boxed;
563 564 565 566
    return arg_cache;
}

static inline PyGIArgCache *
John (J5) Palmieri's avatar
John (J5) Palmieri committed
567
_arg_cache_new_for_in_interface_callback(PyGIFunctionCache *function_cache,
568 569
                                         GIArgInfo *arg_info,
                                         GIInterfaceInfo *iface_info)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
570
{
571
    PyGICallbackCache *callback_cache = _callback_cache_new_from_arg_info(arg_info, iface_info, function_cache->is_method ? 1: 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
572 573 574 575 576 577
    PyGIArgCache *arg_cache = (PyGIArgCache *)callback_cache;
    if (callback_cache->user_data_index >= 0) {
        PyGIArgCache *user_data_arg_cache = _arg_cache_new();
        user_data_arg_cache->aux_type = PYGI_AUX_TYPE_HAS_PYARG;
        function_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
    }
578 579

    if (callback_cache->destroy_notify_index >= 0) {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
580 581 582 583 584
        PyGIArgCache *destroy_arg_cache = _arg_cache_new();
        destroy_arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
        function_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
    }
    arg_cache->in_marshaller = _pygi_marshal_in_interface_callback;
585 586 587 588
    return arg_cache;
}

static inline PyGIArgCache *
589
_arg_cache_new_for_in_interface_enum(GIInterfaceInfo *iface_info)
590
{
591 592 593 594
    PyGIInterfaceCache *iface_cache = _interface_cache_new_from_interface_info(iface_info);
    PyGIArgCache *arg_cache = (PyGIArgCache *)iface_cache;

    arg_cache->in_marshaller = _pygi_marshal_in_interface_enum;
595 596 597 598
    return arg_cache;
}

static inline PyGIArgCache *
599
_arg_cache_new_for_in_interface_flags(GIInterfaceInfo *iface_info)
600
{
601 602 603 604
    PyGIInterfaceCache *iface_cache = _interface_cache_new_from_interface_info(iface_info);
    PyGIArgCache *arg_cache = (PyGIArgCache *)iface_cache; 

    arg_cache->in_marshaller = _pygi_marshal_in_interface_flags;
605 606 607 608 609
    return arg_cache;
}

PyGIArgCache *
_arg_cache_in_new_from_interface_info (GIInterfaceInfo *iface_info,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
610
                                       GIArgInfo *arg_info,
611 612 613 614 615 616 617 618 619 620 621
                                       PyGIFunctionCache *function_cache,
                                       GIInfoType info_type,
                                       GITransfer transfer,
                                       GIDirection direction,
                                       gint c_arg_index,
                                       gint py_arg_index)
{
    PyGIArgCache *arg_cache = NULL;

    switch (info_type) {
        case GI_INFO_TYPE_UNION:
John (J5) Palmieri's avatar
John (J5) Palmieri committed
622
            arg_cache = _arg_cache_new_for_in_interface_union(iface_info, transfer);
623 624
            break;
        case GI_INFO_TYPE_STRUCT:
625 626
            arg_cache = _arg_cache_new_for_in_interface_struct(iface_info,
                                                               transfer);
627 628 629
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
630 631
            arg_cache = _arg_cache_new_for_in_interface_object(iface_info,
                                                               transfer);
632 633
            break;
        case GI_INFO_TYPE_BOXED:
634 635
            arg_cache = _arg_cache_new_for_in_interface_boxed(iface_info,
                                                              transfer);
636 637
            break;
        case GI_INFO_TYPE_CALLBACK:
John (J5) Palmieri's avatar
John (J5) Palmieri committed
638
            arg_cache = _arg_cache_new_for_in_interface_callback(function_cache,
639 640
                                                                 arg_info,
                                                                 iface_info);
641 642
            break;
        case GI_INFO_TYPE_ENUM:
643
            arg_cache = _arg_cache_new_for_in_interface_enum(iface_info);
644 645
            break;
        case GI_INFO_TYPE_FLAGS:
646
            arg_cache = _arg_cache_new_for_in_interface_flags(iface_info);
647 648 649 650 651 652 653 654 655 656 657
            break;
        default:
            g_assert_not_reached();
    }

    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;
658 659 660

        g_base_info_ref( (GIBaseInfo *)iface_info);
        ((PyGIInterfaceCache *)arg_cache)->interface_info = iface_info; 
661
    }
662 663

    return arg_cache;
664 665
}

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798
/* process out args */

static inline PyGIArgCache *
_arg_cache_new_for_out_void(void)
{
     PyGIArgCache *arg_cache = _arg_cache_new();
     arg_cache->out_marshaller = _pygi_marshal_out_void;
     return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_boolean(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_boolean;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_int8(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_int8;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_uint8(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_uint8;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_int16(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_int16;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_uint16(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_uint16;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_int32(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_int32;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_uint32(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_uint32;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_int64(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_int64;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_uint64(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_uint64;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_float(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_float;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_double(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_double;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_unichar(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_unichar;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_gtype(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_gtype;
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_utf8(GITransfer transfer)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_utf8;

    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_filename(GITransfer transfer)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_filename;

    return arg_cache;
}

static inline PyGIArgCache *
799 800 801 802 803 804 805 806 807 808 809
_arg_cache_new_for_out_array(PyGIFunctionCache *function_cache,
                             GITypeInfo *type_info,
                             GITransfer transfer)
{
    PyGISequenceCache *seq_cache =
        _sequence_cache_new_from_type_info(type_info,
                                           GI_DIRECTION_OUT,
                                           transfer,
                                           function_cache->is_method ? 1: 0);
    PyGIArgCache *arg_cache = (PyGIArgCache *)seq_cache;

810 811
    arg_cache->out_marshaller = _pygi_marshal_out_array;

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
    seq_cache->array_type = g_type_info_get_array_type(type_info);

    if (seq_cache->len_arg_index >= 0) {
        PyGIArgCache *aux_cache = _arg_cache_new();
        aux_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
        if (function_cache->args_cache[seq_cache->len_arg_index] != NULL) {
            PyGIArgCache *invalid_cache = function_cache->args_cache[seq_cache->len_arg_index];
            arg_cache->c_arg_index = invalid_cache->c_arg_index;
            _pygi_arg_cache_free(invalid_cache);
        }

        function_cache->args_cache[seq_cache->len_arg_index] = aux_cache;
    }


827 828 829 830 831 832
    /* arg_cache->cleanup = _pygi_cleanup_array; */
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_glist(GITypeInfo *type_info,
833
                             GITransfer transfer)
834
{
835
    PyGIArgCache *arg_cache =
836 837 838 839
       (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info,
                                                          GI_DIRECTION_OUT,
                                                          transfer,
                                                          0);
840 841 842 843 844 845 846 847
    arg_cache->out_marshaller = _pygi_marshal_out_glist;
    /* arg_cache->cleanup = */

    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_gslist(GITypeInfo *type_info,
848
                              GITransfer transfer)
849
{
850
    PyGIArgCache *arg_cache =
851 852 853 854
        (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info,
                                                           GI_DIRECTION_OUT,
                                                           transfer,
                                                           0);
855 856 857 858 859 860 861 862 863 864 865 866
    arg_cache->out_marshaller = _pygi_marshal_out_gslist;
    /* arg_cache->cleanup = */

    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_ghash(GITypeInfo *type_info)
{
    PyGIArgCache *arg_cache = NULL;
    /*arg_cache->out_marshaller = _pygi_marshal_out_ghash;*/
    PyErr_Format(PyExc_NotImplementedError,
867
                 "Caching for Out GHash is not fully implemented yet");
868 869 870 871 872 873 874 875
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_gerror(void)
{
    PyGIArgCache *arg_cache = _arg_cache_new();
    arg_cache->out_marshaller = _pygi_marshal_out_gerror;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
876
    arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
877 878
    return arg_cache;
}
879 880 881 882 883 884 885
static inline PyGIArgCache *
_arg_cache_new_for_out_interface_struct(GIInterfaceInfo *iface_info,
                                        GITransfer transfer)
{
    PyGIInterfaceCache *iface_cache = _interface_cache_new_from_interface_info(iface_info);
    PyGIArgCache *arg_cache = (PyGIArgCache *)iface_cache;
    iface_cache->is_foreign = g_struct_info_is_foreign( (GIStructInfo*)iface_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
886
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902

    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_interface_object(GIInterfaceInfo *iface_info,
                                        GITransfer transfer)
{
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
    arg_cache->out_marshaller = _pygi_marshal_out_interface_object;

    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_interface_boxed(GIInterfaceInfo *iface_info,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
903
                                       GITransfer transfer)
904 905
{
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
906
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
907 908 909 910 911 912 913 914 915 916
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_out_interface_callback(void)
{
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
    return FALSE;
}
917

918
static inline PyGIArgCache *
919 920
_arg_cache_new_for_out_interface_enum(GIInterfaceInfo *iface_info,
                                      GITransfer transfer)
921
{
922 923
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
    arg_cache->out_marshaller = _pygi_marshal_out_interface_enum;
924 925 926 927
    return arg_cache;
}

static inline PyGIArgCache *
John (J5) Palmieri's avatar
John (J5) Palmieri committed
928 929
_arg_cache_new_for_out_interface_union(GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
930
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
931 932
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
933 934
    return arg_cache;
}
John (J5) Palmieri's avatar
John (J5) Palmieri committed
935

936
static inline PyGIArgCache *
937 938
_arg_cache_new_for_out_interface_flags(GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
939
{
940 941
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
    arg_cache->out_marshaller = _pygi_marshal_out_interface_flags;
942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
    return arg_cache;
}

PyGIArgCache *
_arg_cache_out_new_from_interface_info (GIInterfaceInfo *iface_info,
                                        PyGIFunctionCache *function_cache,
                                        GIInfoType info_type,
                                        GITransfer transfer,
                                        GIDirection direction,
                                        gint c_arg_index)
{
    PyGIArgCache *arg_cache = NULL;

    switch (info_type) {
        case GI_INFO_TYPE_UNION:
John (J5) Palmieri's avatar
John (J5) Palmieri committed
957
            arg_cache = _arg_cache_new_for_out_interface_union(iface_info, transfer);
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
            break;
        case GI_INFO_TYPE_STRUCT:
            arg_cache = _arg_cache_new_for_out_interface_struct(iface_info,
                                                               transfer);
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
            arg_cache = _arg_cache_new_for_out_interface_object(iface_info,
                                                                transfer);
            break;
        case GI_INFO_TYPE_BOXED:
            arg_cache = _arg_cache_new_for_out_interface_boxed(iface_info,
                                                               transfer);
            break;
        case GI_INFO_TYPE_CALLBACK:
            arg_cache = _arg_cache_new_for_out_interface_callback();
            break;
        case GI_INFO_TYPE_ENUM:
976 977
            arg_cache = _arg_cache_new_for_out_interface_enum(iface_info,
                                                              transfer);
978 979
            break;
        case GI_INFO_TYPE_FLAGS:
980 981
            arg_cache = _arg_cache_new_for_out_interface_flags(iface_info,
                                                               transfer);
982 983 984 985 986 987 988 989 990 991
            break;
        default:
            g_assert_not_reached();
    }

    if (arg_cache != NULL) {
        arg_cache->direction = direction;