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
}