pygi-cache.c 22.8 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 29 30 31 32 33 34
PyGIArgCache * _arg_cache_in_new_from_type_info (GITypeInfo *type_info,
                                  PyGIFunctionCache *function_cache,
                                  GITypeTag type_tag,
                                  GITransfer transfer,
                                  GIDirection direction,
                                  gint c_arg_index,
                                  gint py_arg_index);
35 36
/* cleanup */
static inline void
37
_interface_cache_free_func (PyGIInterfaceCache *cache)
38 39 40 41
{
    if (cache != NULL) {
        Py_XDECREF(cache->py_type);
        g_slice_free(PyGIInterfaceCache, cache);
42 43
        if (cache->type_name != NULL)
            g_free(cache->type_name);
44 45 46 47 48 49 50 51 52 53
    }
}

static inline void
_pygi_hash_cache_free (PyGIHashCache *cache)
{
    if (cache != NULL)
        g_slice_free(PyGIHashCache, cache);
}

54 55
static void
_sequence_cache_free_func (PyGISequenceCache *cache)
56 57 58 59 60
{
    if (cache != NULL)
        g_slice_free(PyGISequenceCache, cache);
}

61 62
static void
_callback_cache_free_func (PyGICallbackCache *cache)
63 64 65 66 67 68
{
    if (cache != NULL)
        g_slice_free(PyGICallbackCache, cache);
}

void
69
_pygi_arg_cache_free (PyGIArgCache *cache)
70
{
71 72 73 74 75
    if (cache == NULL)
        return;

    if (cache->arg_info != NULL)
        g_base_info_unref(cache->arg_info);
76 77 78 79
    if (cache->destroy_notify)
        cache->destroy_notify(cache);
    else
        g_slice_free(PyGIArgCache, cache);
80 81 82 83 84 85 86
}

void
_pygi_function_cache_free (PyGIFunctionCache *cache)
{
    int i;

87 88 89
    if (cache == NULL)
        return;

90 91 92 93
    g_slist_free(cache->in_args);
    g_slist_free(cache->out_args);
    for (i = 0; i < cache->n_args; i++) {
        PyGIArgCache *tmp = cache->args_cache[i];
94
        _pygi_arg_cache_free(tmp);
95
    }
96
    g_slice_free1(cache->n_args * sizeof(PyGIArgCache *), cache->args_cache);
97 98 99 100 101
    g_slice_free(PyGIFunctionCache, cache);
}

/* cache generation */
static inline PyGIFunctionCache *
102
_function_cache_new_from_function_info(GIFunctionInfo *function_info)
103 104 105 106 107 108 109 110
{
    PyGIFunctionCache *fc;
    GIFunctionInfoFlags flags;

    fc = g_slice_new0(PyGIFunctionCache);
    flags = g_function_info_get_flags(function_info);
    fc->is_method = flags & GI_FUNCTION_IS_METHOD;
    fc->is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
111

112
    fc->n_args = g_callable_info_get_n_args ( (GICallableInfo *) function_info) + (fc->is_method ? 1: 0);
113 114
    if (fc->n_args > 0)
        fc->args_cache = g_slice_alloc0(fc->n_args * sizeof(PyGIArgCache *));
115 116 117 118

    return fc;
}

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

static inline PyGIInterfaceCache *
_interface_cache_new_from_interface_info(GIInterfaceInfo *iface_info)
{
    PyGIInterfaceCache *ic;
    
    ic = g_slice_new0(PyGIInterfaceCache);
    ((PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;    
    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;

    ic->type_name == _pygi_g_base_info_get_fullname(iface_info);
    return ic;
}

142
static inline PyGISequenceCache *
143 144 145 146
_sequence_cache_new_from_type_info(GITypeInfo *type_info)
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
147
    GITypeTag item_type_tag;
148 149

    sc = g_slice_new0(PyGISequenceCache);
150
    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;    
151 152 153 154

    sc->fixed_size = -1;
    sc->len_arg_index = -1;
    sc->is_zero_terminated = g_type_info_is_zero_terminated(type_info);
155
    if (!sc->is_zero_terminated)
156 157
        sc->fixed_size = g_type_info_get_array_fixed_size(type_info);
    if (sc->fixed_size < 0)
158 159
        sc->len_arg_index = g_type_info_get_array_length (type_info);

160
    item_type_info = g_type_info_get_param_type (type_info, 0);
161
    item_type_tag = g_type_info_get_tag (item_type_info);
162

163 164 165 166 167 168 169 170
    /* FIXME: support out also */
    sc->item_cache = _arg_cache_in_new_from_type_info(item_type_info,
                                                      NULL,
                                                      item_type_tag,
                                                      GI_TRANSFER_EVERYTHING,
                                                      GI_DIRECTION_IN,
                                                      0, 0);

171 172 173 174 175 176
    if (sc->item_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)sc);
        return NULL;
    }
   
    sc->item_cache->type_tag = item_type_tag;    
177
    g_base_info_unref( (GIBaseInfo *) item_type_info);
178

179
    return sc;
180 181
}

182 183 184 185 186
static inline PyGIArgCache *
_arg_cache_new(void)
{
    return g_slice_new0(PyGIArgCache);
}
187 188
/* process in args */

189 190
static inline PyGIArgCache *
_arg_cache_new_for_in_void(void)
191
{
192
     PyGIArgCache *arg_cache = _arg_cache_new();
193
     arg_cache->in_marshaller = _pygi_marshal_in_void;
194

195
     return arg_cache;
196 197
}

198 199
static inline PyGIArgCache *
_arg_cache_new_for_in_boolean(void)
200
{
201
    PyGIArgCache *arg_cache = _arg_cache_new();
202
    arg_cache->in_marshaller = _pygi_marshal_in_boolean;
203
    return arg_cache;
204 205
}

206 207
static inline PyGIArgCache *
_arg_cache_new_for_in_int8(void)
208
{
209
    PyGIArgCache *arg_cache = _arg_cache_new();
210
    arg_cache->in_marshaller = _pygi_marshal_in_int8;
211
    return arg_cache;
212 213
}

214 215
static inline PyGIArgCache *
_arg_cache_new_for_in_uint8(void)
216
{
217
    PyGIArgCache *arg_cache = _arg_cache_new();
218
    arg_cache->in_marshaller = _pygi_marshal_in_uint8;
219
    return arg_cache;
220 221
}

222 223
static inline PyGIArgCache *
_arg_cache_new_for_in_int16(void)
224
{
225
    PyGIArgCache *arg_cache = _arg_cache_new();
226
    arg_cache->in_marshaller = _pygi_marshal_in_int16;
227
    return arg_cache;
228 229
}

230 231
static inline PyGIArgCache *
_arg_cache_new_for_in_uint16(void)
232
{
233
    PyGIArgCache *arg_cache = _arg_cache_new();
234
    arg_cache->in_marshaller = _pygi_marshal_in_uint16;
235
    return arg_cache;
236 237
}

238 239
static inline PyGIArgCache *
_arg_cache_new_for_in_int32(void)
240
{
241
    PyGIArgCache *arg_cache = _arg_cache_new();
242
    arg_cache->in_marshaller = _pygi_marshal_in_int32;
243
    return arg_cache;
244 245
}

246 247
static inline PyGIArgCache *
_arg_cache_new_for_in_uint32(void)
248
{
249
    PyGIArgCache *arg_cache = _arg_cache_new();
250
    arg_cache->in_marshaller = _pygi_marshal_in_uint32;
251
    return arg_cache;
252 253
}

254 255
static inline PyGIArgCache *
_arg_cache_new_for_in_int64(void)
256
{
257
    PyGIArgCache *arg_cache = _arg_cache_new();
258
    arg_cache->in_marshaller = _pygi_marshal_in_int64;
259
    return arg_cache;
260 261
}

262 263
static inline PyGIArgCache *
_arg_cache_new_for_in_uint64(void)
264
{
265
    PyGIArgCache *arg_cache = _arg_cache_new();
266
    arg_cache->in_marshaller = _pygi_marshal_in_uint64;
267
    return arg_cache;
268 269
}

270 271
static inline PyGIArgCache *
_arg_cache_new_for_in_float(void)
272
{
273
    PyGIArgCache *arg_cache = _arg_cache_new();
274
    arg_cache->in_marshaller = _pygi_marshal_in_float;
275
    return arg_cache;
276 277
}

278 279
static inline PyGIArgCache *
_arg_cache_new_for_in_double(void)
280
{
281
    PyGIArgCache *arg_cache = _arg_cache_new();
282
    arg_cache->in_marshaller = _pygi_marshal_in_double;
283
    return arg_cache;
284 285
}

286 287
static inline PyGIArgCache *
_arg_cache_new_for_in_unichar(void)
288
{
289
    PyGIArgCache *arg_cache = _arg_cache_new();
290
    arg_cache->in_marshaller = _pygi_marshal_in_unichar;
291
    return arg_cache;
292 293
}

294 295
static inline PyGIArgCache *
_arg_cache_new_for_in_gtype(void)
296
{
297
    PyGIArgCache *arg_cache = _arg_cache_new();
298
    arg_cache->in_marshaller = _pygi_marshal_in_gtype;
299
    return arg_cache;
300 301
}

302 303
static inline PyGIArgCache *
_arg_cache_new_for_in_utf8(GITransfer transfer)
304
{
305
    PyGIArgCache *arg_cache = _arg_cache_new();
306
    arg_cache->in_marshaller = _pygi_marshal_in_utf8;
307 308 309
    if (arg_cache->transfer == GI_TRANSFER_NOTHING)
        arg_cache->cleanup = g_free;

310
    return arg_cache;
311 312
}

313 314
static inline PyGIArgCache *
_arg_cache_new_for_in_filename(GITransfer transfer)
315
{
316
    PyGIArgCache *arg_cache = _arg_cache_new();
317
    arg_cache->in_marshaller = _pygi_marshal_in_filename;
318 319 320
    if (arg_cache->transfer == GI_TRANSFER_NOTHING)
        arg_cache->cleanup = g_free;

321
    return arg_cache;
322 323
}

324 325
static inline PyGIArgCache *
_arg_cache_new_for_in_array(GITypeInfo *type_info,
326
                            GITransfer transfer)
327
{
328
    PyGIArgCache *arg_cache = (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info);
329
    arg_cache->in_marshaller = _pygi_marshal_in_array;
330 331

    /* arg_cache->cleanup = _pygi_cleanup_array; */
332
    return arg_cache;
333 334
}

335 336 337
static inline PyGIArgCache *
_arg_cache_new_for_in_glist(GITypeInfo *type_info,
                                      GITransfer transfer)
338
{
339
    PyGIArgCache *arg_cache = (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info);
340
    arg_cache->in_marshaller = _pygi_marshal_in_glist;
341 342
    /* arg_cache->cleanup = */

343
    return arg_cache;
344 345
}

346 347 348
static inline PyGIArgCache *
_arg_cache_new_for_in_gslist(GITypeInfo *type_info,
                                       GITransfer transfer)
349
{
350
    PyGIArgCache *arg_cache = (PyGIArgCache *)_sequence_cache_new_from_type_info(type_info);
351
    arg_cache->in_marshaller = _pygi_marshal_in_gslist;
352 353
    /* arg_cache->cleanup = */

354
    return arg_cache;
355 356
}

357 358
static inline PyGIArgCache *
_arg_cache_new_for_in_ghash(GITypeInfo *type_info)
359
{
360 361
    PyGIArgCache *arg_cache = NULL;
    /*arg_cache->in_marshaller = _pygi_marshal_in_ghash;*/
362 363
    PyErr_Format(PyExc_NotImplementedError,
                 "Caching for this type is not fully implemented yet");
364
    return arg_cache;
365 366
}

367 368
static inline PyGIArgCache *
_arg_cache_new_for_in_gerror(void)
369
{
370
    PyGIArgCache *arg_cache = _arg_cache_new();
371
    arg_cache->in_marshaller = _pygi_marshal_in_gerror;
372
    arg_cache->is_aux = TRUE;
373
    return arg_cache;
374 375
}

376 377 378 379 380 381 382 383 384 385
static inline PyGIArgCache *
_arg_cache_new_for_in_interface_union(void)
{
    PyGIArgCache *arg_cache = NULL;
    /*arg_cache->in_marshaller = _pygi_marshal_in_inteface_union;*/
    PyErr_Format(PyExc_NotImplementedError,
                 "Caching for this type is not fully implemented yet");
    return arg_cache;
}

386 387 388 389 390 391

static void 
_g_slice_free_gvalue_func(GValue *value) {
    g_slice_free(GValue, value);
}

392
static inline PyGIArgCache *
393 394
_arg_cache_new_for_in_interface_struct(GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
395
{
396 397 398 399 400 401 402 403 404
    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);
    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;

405 406 407 408
    return arg_cache;
}

static inline PyGIArgCache *
409 410
_arg_cache_new_for_in_interface_object(GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
411
{
412
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
413 414 415 416 417 418 419 420
    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 *
421 422
_arg_cache_new_for_in_interface_boxed(GIInterfaceInfo *iface_info,
                                      GITransfer transfer)
423
{
424 425
    PyGIArgCache *arg_cache = (PyGIArgCache *)_interface_cache_new_from_interface_info(iface_info);
    arg_cache->in_marshaller = _pygi_marshal_in_interface_boxed;
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_in_interface_callback(void)
{
    PyGIArgCache *arg_cache = NULL;
    /*arg_cache->in_marshaller = _pygi_marshal_in_callback;*/
    PyErr_Format(PyExc_NotImplementedError,
                 "Caching for this type is not fully implemented yet");
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_in_interface_enum(void)
{
    PyGIArgCache *arg_cache = NULL;
    /*arg_cache->in_marshaller = _pygi_marshal_in_enum;*/
    PyErr_Format(PyExc_NotImplementedError,
                 "Caching for this type is not fully implemented yet");
    return arg_cache;
}

static inline PyGIArgCache *
_arg_cache_new_for_in_interface_flags(void)
{
    PyGIArgCache *arg_cache = NULL;
    /*arg_cache->in_marshaller = _pygi_marshal_in_flags;*/
    PyErr_Format(PyExc_NotImplementedError,
                 "Caching for this type is not fully implemented yet");
    return arg_cache;
}

PyGIArgCache *
_arg_cache_in_new_from_interface_info (GIInterfaceInfo *iface_info,
                                       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:
            arg_cache = _arg_cache_new_for_in_interface_union();
            break;
        case GI_INFO_TYPE_STRUCT:
            arg_cache = _arg_cache_new_for_in_interface_struct();
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
479 480
            arg_cache = _arg_cache_new_for_in_interface_object(iface_info,
                                                               transfer);
481 482
            break;
        case GI_INFO_TYPE_BOXED:
483 484
            arg_cache = _arg_cache_new_for_in_interface_boxed(iface_info,
                                                              transfer);
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
            break;
        case GI_INFO_TYPE_CALLBACK:
            arg_cache = _arg_cache_new_for_in_interface_callback();
            break;
        case GI_INFO_TYPE_ENUM:
            arg_cache = _arg_cache_new_for_in_interface_enum();
            break;
        case GI_INFO_TYPE_FLAGS:
            arg_cache = _arg_cache_new_for_in_interface_flags();
            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;
    }
506 507

    return arg_cache;
508 509 510
}


511 512 513 514 515 516 517 518
PyGIArgCache *
_arg_cache_in_new_from_type_info (GITypeInfo *type_info,
                                  PyGIFunctionCache *function_cache,
                                  GITypeTag type_tag,
                                  GITransfer transfer,
                                  GIDirection direction,
                                  gint c_arg_index,
                                  gint py_arg_index)
519
{
520
    PyGIArgCache *arg_cache = NULL;
521 522 523

    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
524
           arg_cache = _arg_cache_new_for_in_void();
525 526
           break;
       case GI_TYPE_TAG_BOOLEAN:
527
           arg_cache = _arg_cache_new_for_in_boolean();
528 529
           break;
       case GI_TYPE_TAG_INT8:
530
           arg_cache = _arg_cache_new_for_in_int8();
531 532
           break;
       case GI_TYPE_TAG_UINT8:
533
           arg_cache = _arg_cache_new_for_in_uint8();
534 535
           break;
       case GI_TYPE_TAG_INT16:
536
           arg_cache = _arg_cache_new_for_in_uint16();
537 538
           break;
       case GI_TYPE_TAG_UINT16:
539
           arg_cache = _arg_cache_new_for_in_uint16();
540 541
           break;
       case GI_TYPE_TAG_INT32:
542
           arg_cache = _arg_cache_new_for_in_int32();
543 544
           break;
       case GI_TYPE_TAG_UINT32:
545
           arg_cache = _arg_cache_new_for_in_uint32();
546 547
           break;
       case GI_TYPE_TAG_INT64:
548
           arg_cache = _arg_cache_new_for_in_int64();
549 550
           break;
       case GI_TYPE_TAG_UINT64:
551
           arg_cache = _arg_cache_new_for_in_uint64();
552 553
           break;
       case GI_TYPE_TAG_FLOAT:
554
           arg_cache = _arg_cache_new_for_in_float();
555 556
           break;
       case GI_TYPE_TAG_DOUBLE:
557
           arg_cache = _arg_cache_new_for_in_double();
558 559
           break;
       case GI_TYPE_TAG_UNICHAR:
560
           arg_cache = _arg_cache_new_for_in_unichar();
561 562
           break;
       case GI_TYPE_TAG_GTYPE:
563
           arg_cache = _arg_cache_new_for_in_gtype();
564 565
           break;
       case GI_TYPE_TAG_UTF8:
566
           arg_cache = _arg_cache_new_for_in_utf8(transfer);
567 568
           break;
       case GI_TYPE_TAG_FILENAME:
569
           arg_cache = _arg_cache_new_for_in_filename(transfer);
570 571
           break;
       case GI_TYPE_TAG_ARRAY:
572 573
           arg_cache = _arg_cache_new_for_in_array(type_info,
                                                   transfer);
574 575
           break;
       case GI_TYPE_TAG_INTERFACE:
576 577 578 579 580 581 582 583 584 585 586 587 588 589
           {
               GIInterfaceInfo *interface_info = g_type_info_get_interface(type_info);
               GIInfoType info_type = g_base_info_get_type( (GIBaseInfo *) interface_info);
               arg_cache = _arg_cache_in_new_from_interface_info(interface_info,
                                                                 function_cache,
                                                                 info_type,
                                                                 transfer,
                                                                 direction,
                                                                 c_arg_index,
                                                                 py_arg_index);

               g_base_info_unref( (GIBaseInfo *) interface_info);
               return arg_cache;
           }
590
       case GI_TYPE_TAG_GLIST:
591 592
           arg_cache = _arg_cache_new_for_in_glist(type_info,
                                                   transfer);
593 594
           break;
       case GI_TYPE_TAG_GSLIST:
595 596
           arg_cache = _arg_cache_new_for_in_gslist(type_info,
                                                    transfer);
597 598
           break;
       case GI_TYPE_TAG_GHASH:
599
           arg_cache = _arg_cache_new_for_in_ghash(type_info);
600 601
           break;
       case GI_TYPE_TAG_ERROR:
602
           arg_cache = _arg_cache_new_for_in_gerror();
603 604 605
           break;
    }

606 607 608 609 610 611 612 613 614
    if (arg_cache != NULL) {
        arg_cache->direction = direction;
        arg_cache->transfer = transfer;
        arg_cache->type_tag = type_tag;
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
    }

    return arg_cache;
615 616
}

617
static inline gboolean
John (J5) Palmieri's avatar
John (J5) Palmieri committed
618
_args_cache_generate(GIFunctionInfo *function_info,
619 620
                     PyGIFunctionCache *function_cache)
{
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
    int arg_index = 0;
    /* first arg is the instance */
    if (function_cache->is_method) {
        GIInterfaceInfo *interface_info;
        PyGIArgCache *instance_cache;
        GIInfoType info_type;

        interface_info = g_base_info_get_container ( (GIBaseInfo *) function_info);
        info_type = g_base_info_get_type(interface_info);

        instance_cache =
            _arg_cache_in_new_from_interface_info(interface_info,
                                                  function_cache,
                                                  info_type,
                                                  GI_TRANSFER_NOTHING,
                                                  GI_DIRECTION_IN,
                                                  arg_index,
                                                  0);

        g_base_info_unref( (GIBaseInfo *) interface_info);

        if (instance_cache == NULL)
            return FALSE;

        function_cache->args_cache[arg_index] = instance_cache;
        
        arg_index++;
        function_cache->n_in_args++;
    }

651 652

    for (; arg_index < function_cache->n_args; arg_index++) {
653
        PyGIArgCache *arg_cache = NULL;
654
        GIArgInfo *arg_info;
655
        GITypeInfo *type_info;
656 657 658 659
        GIDirection direction;
        GITransfer transfer;
        GITypeTag type_tag;
        gint py_arg_index;
660 661

        /* must be an aux arg filled in by its owner so skip */
662
        if (function_cache->args_cache[arg_index] != NULL)
663 664
            continue;

John (J5) Palmieri's avatar
John (J5) Palmieri committed
665
        arg_info =
666
            g_callable_info_get_arg( (GICallableInfo *) function_info, arg_index);
667

668 669
        direction = g_arg_info_get_direction(arg_info);
        transfer = g_arg_info_get_ownership_transfer(arg_info);
670
        type_info = g_arg_info_get_type(arg_info);
671
        type_tag = g_type_info_get_tag(type_info);
672

673
        switch(direction) {
674
            case GI_DIRECTION_IN:
675
                py_arg_index = function_cache->n_in_args;
676
                function_cache->n_in_args++;
677

678 679 680 681 682 683 684 685
                arg_cache =
                    _arg_cache_in_new_from_type_info(type_info,
                                                     function_cache,
                                                     type_tag,
                                                     transfer,
                                                     direction,
                                                     arg_index,
                                                     py_arg_index);
686

687 688 689
                if (arg_cache == NULL)
                    goto arg_err;

690 691
                function_cache->in_args =
                    g_slist_append(function_cache->in_args, arg_cache);
692
                break;
693 694

            case GI_DIRECTION_OUT:
695
                function_cache->n_out_args++;
696 697 698 699 700 701 702 703 704 705
                PyErr_Format(PyExc_NotImplementedError,
                             "Out caching is not fully implemented yet");

                goto arg_err;

            case GI_DIRECTION_INOUT:
                PyErr_Format(PyExc_NotImplementedError,
                             "In/Out caching is not fully implemented yet");
                goto arg_err;

706
        }
707 708

        function_cache->args_cache[arg_index] = arg_cache;
709
        g_base_info_unref( (GIBaseInfo *) type_info);
710 711 712 713
        continue;
arg_err:
        g_base_info_unref( (GIBaseInfo *) type_info);
        return FALSE;
714
    }
715
    return TRUE;
716 717 718 719 720
}

PyGIFunctionCache *
_pygi_function_cache_new (GIFunctionInfo *function_info)
{
721
    PyGIFunctionCache *fc = _function_cache_new_from_function_info(function_info);
722 723 724
    if (fc == NULL)
        return NULL;

725 726 727
    if (!_args_cache_generate(function_info, fc))
        goto err;

728
    return fc;
729 730
err:
    _pygi_function_cache_free(fc);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
731
    return NULL;
732
}