1 /*
2 XS code to test the typemap entries
3
4 Copyright (C) 2001 Tim Jenness.
5 All Rights Reserved
6
7 */
8
9 #define PERL_NO_GET_CONTEXT
10
11 #include "EXTERN.h" /* std perl include */
12 #include "perl.h" /* std perl include */
13 #include "XSUB.h" /* XSUB include */
14
15 /* Prototypes for external functions */
16 FILE * xsfopen( const char * );
17 int xsfclose( FILE * );
18 int xsfprintf( FILE *, const char *);
19
20 /* Type definitions required for the XS typemaps */
21 typedef SV * SVREF; /* T_SVREF */
22 typedef int SysRet; /* T_SYSRET */
23 typedef int Int; /* T_INT */
24 typedef int intRef; /* T_PTRREF */
25 typedef int intObj; /* T_PTROBJ */
26 typedef int intRefIv; /* T_REF_IV_PTR */
27 typedef int intArray; /* T_ARRAY */
28 typedef int intTINT; /* T_INT */
29 typedef int intTLONG; /* T_LONG */
30 typedef short shortOPQ; /* T_OPAQUE */
31 typedef int intOpq; /* T_OPAQUEPTR */
32 typedef unsigned intUnsigned; /* T_U_INT */
33 typedef PerlIO * inputfh; /* T_IN */
34 typedef PerlIO * outputfh; /* T_OUT */
35
36 /* A structure to test T_OPAQUEPTR and T_PACKED */
37 struct t_opaqueptr {
38 int a;
39 int b;
40 double c;
41 };
42
43 typedef struct t_opaqueptr astruct;
44 typedef struct t_opaqueptr anotherstruct;
45
46 /* Some static memory for the tests */
47 static I32 xst_anint;
48 static intRef xst_anintref;
49 static intObj xst_anintobj;
50 static intRefIv xst_anintrefiv;
51 static intOpq xst_anintopq;
52
53 /* A different type to refer to for testing the different
54 * AV*, HV*, etc typemaps */
55 typedef AV AV_FIXED;
56 typedef HV HV_FIXED;
57 typedef CV CV_FIXED;
58 typedef SVREF SVREF_FIXED;
59
60 /* Helper functions */
61
62 /* T_ARRAY - allocate some memory */
intArrayPtr(int nelem)63 intArray * intArrayPtr( int nelem ) {
64 intArray * array;
65 Newx(array, nelem, intArray);
66 return array;
67 }
68
69 /* test T_PACKED */
70 STATIC void
XS_pack_anotherstructPtr(SV * out,anotherstruct * in)71 XS_pack_anotherstructPtr(SV *out, anotherstruct *in)
72 {
73 dTHX;
74 HV *hash = newHV();
75 if (NULL == hv_stores(hash, "a", newSViv(in->a)))
76 croak("Failed to store data in hash");
77 if (NULL == hv_stores(hash, "b", newSViv(in->b)))
78 croak("Failed to store data in hash");
79 if (NULL == hv_stores(hash, "c", newSVnv(in->c)))
80 croak("Failed to store data in hash");
81 sv_setsv(out, sv_2mortal(newRV_noinc((SV*)hash)));
82 }
83
84 STATIC anotherstruct *
XS_unpack_anotherstructPtr(SV * in)85 XS_unpack_anotherstructPtr(SV *in)
86 {
87 dTHX; /* rats, this is expensive */
88 /* this is similar to T_HVREF since we chose to use a hash */
89 HV *inhash;
90 SV **elem;
91 anotherstruct *out;
92 SV *const tmp = in;
93 SvGETMAGIC(tmp);
94 if (SvROK(tmp) && SvTYPE(SvRV(tmp)) == SVt_PVHV)
95 inhash = (HV*)SvRV(tmp);
96 else
97 Perl_croak(aTHX_ "Argument is not a HASH reference");
98
99 /* FIXME dunno if supposed to use perl mallocs here */
100 Newxz(out, 1, anotherstruct);
101
102 elem = hv_fetchs(inhash, "a", 0);
103 if (elem == NULL)
104 Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
105 out->a = SvIV(*elem);
106
107 elem = hv_fetchs(inhash, "b", 0);
108 if (elem == NULL)
109 Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
110 out->b = SvIV(*elem);
111
112 elem = hv_fetchs(inhash, "c", 0);
113 if (elem == NULL)
114 Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
115 out->c = SvNV(*elem);
116
117 return out;
118 }
119
120 /* test T_PACKEDARRAY */
121 STATIC void
XS_pack_anotherstructPtrPtr(SV * out,anotherstruct ** in,UV cnt)122 XS_pack_anotherstructPtrPtr(SV *out, anotherstruct **in, UV cnt)
123 {
124 dTHX;
125 UV i;
126 AV *ary = newAV();
127 for (i = 0; i < cnt; ++i) {
128 HV *hash = newHV();
129 if (NULL == hv_stores(hash, "a", newSViv(in[i]->a)))
130 croak("Failed to store data in hash");
131 if (NULL == hv_stores(hash, "b", newSViv(in[i]->b)))
132 croak("Failed to store data in hash");
133 if (NULL == hv_stores(hash, "c", newSVnv(in[i]->c)))
134 croak("Failed to store data in hash");
135 av_push(ary, newRV_noinc((SV*)hash));
136 }
137 sv_setsv(out, sv_2mortal(newRV_noinc((SV*)ary)));
138 }
139
140 STATIC anotherstruct **
XS_unpack_anotherstructPtrPtr(SV * in)141 XS_unpack_anotherstructPtrPtr(SV *in)
142 {
143 dTHX; /* rats, this is expensive */
144 /* this is similar to T_HVREF since we chose to use a hash */
145 HV *inhash;
146 AV *inary;
147 SV **elem;
148 anotherstruct **out;
149 UV nitems, i;
150 SV *tmp;
151
152 /* safely deref the input array ref */
153 tmp = in;
154 SvGETMAGIC(tmp);
155 if (SvROK(tmp) && SvTYPE(SvRV(tmp)) == SVt_PVAV)
156 inary = (AV*)SvRV(tmp);
157 else
158 Perl_croak(aTHX_ "Argument is not an ARRAY reference");
159
160 nitems = av_count(inary);
161
162 /* FIXME dunno if supposed to use perl mallocs here */
163 /* N+1 elements so we know the last one is NULL */
164 Newxz(out, nitems+1, anotherstruct*);
165
166 /* WARNING: in real code, we'd have to Safefree() on exception, but
167 * since we're testing perl, if we croak() here, stuff is
168 * rotten anyway! */
169 for (i = 0; i < nitems; ++i) {
170 Newxz(out[i], 1, anotherstruct);
171 elem = av_fetch(inary, i, 0);
172 if (elem == NULL)
173 Perl_croak(aTHX_ "Shouldn't happen: av_fetch returns NULL");
174 tmp = *elem;
175 SvGETMAGIC(tmp);
176 if (SvROK(tmp) && SvTYPE(SvRV(tmp)) == SVt_PVHV)
177 inhash = (HV*)SvRV(tmp);
178 else
179 Perl_croak(aTHX_ "Array element %" UVuf
180 " is not a HASH reference", i);
181
182 elem = hv_fetchs(inhash, "a", 0);
183 if (elem == NULL)
184 Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
185 out[i]->a = SvIV(*elem);
186
187 elem = hv_fetchs(inhash, "b", 0);
188 if (elem == NULL)
189 Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
190 out[i]->b = SvIV(*elem);
191
192 elem = hv_fetchs(inhash, "c", 0);
193 if (elem == NULL)
194 Perl_croak(aTHX_ "Shouldn't happen: hv_fetchs returns NULL");
195 out[i]->c = SvNV(*elem);
196 }
197
198 return out;
199 }
200
201 /* no special meaning as far as typemaps are concerned,
202 * just for convenience */
203 void
XS_release_anotherstructPtrPtr(anotherstruct ** in)204 XS_release_anotherstructPtrPtr(anotherstruct **in)
205 {
206 unsigned int i;
207 for (i = 0; in[i] != NULL; i++)
208 Safefree(in[i]);
209 Safefree(in);
210 }
211
212
213 MODULE = XS::Typemap PACKAGE = XS::Typemap
214
215 PROTOTYPES: DISABLE
216
217 TYPEMAP: <<END_OF_TYPEMAP
218
219 # Typemap file for typemap testing
220 # includes bonus typemap entries
221 # Mainly so that all the standard typemaps can be exercised even when
222 # there is not a corresponding type explicitly identified in the standard
223 # typemap
224
225 svtype T_ENUM
226 intRef * T_PTRREF
227 intRef T_IV
228 intObj * T_PTROBJ
229 intObj T_IV
230 intRefIv * T_REF_IV_PTR
231 intRefIv T_IV
232 intArray * T_ARRAY
233 intOpq T_IV
234 intOpq * T_OPAQUEPTR
235 intUnsigned T_U_INT
236 intTINT T_INT
237 intTLONG T_LONG
238 shortOPQ T_OPAQUE
239 shortOPQ * T_OPAQUEPTR
240 astruct * T_OPAQUEPTR
241 anotherstruct * T_PACKED
242 anotherstruct ** T_PACKEDARRAY
243 AV_FIXED * T_AVREF_REFCOUNT_FIXED
244 HV_FIXED * T_HVREF_REFCOUNT_FIXED
245 CV_FIXED * T_CVREF_REFCOUNT_FIXED
246 SVREF_FIXED T_SVREF_REFCOUNT_FIXED
247 inputfh T_IN
248 outputfh T_OUT
249
250 END_OF_TYPEMAP
251
252
253 ## T_SV
254
255 SV *
256 T_SV( sv )
257 SV * sv
258 CODE:
259 /* create a new sv for return that is a copy of the input
260 do not simply copy the pointer since the SV will be marked
261 mortal by the INPUT typemap when it is pushed back onto the stack */
262 RETVAL = sv_mortalcopy( sv );
263 /* increment the refcount since the default INPUT typemap mortalizes
264 by default and we don't want to decrement the ref count twice
265 by mistake */
266 SvREFCNT_inc(RETVAL);
267 OUTPUT:
268 RETVAL
269
270
271 ## T_SVREF
272
273 SVREF
274 T_SVREF( svref )
275 SVREF svref
276 CODE:
277 RETVAL = svref;
278 OUTPUT:
279 RETVAL
280
281
282 ## T_SVREF_FIXED
283
284 SVREF_FIXED
285 T_SVREF_REFCOUNT_FIXED( svref )
286 SVREF_FIXED svref
287 CODE:
288 SvREFCNT_inc(svref);
289 RETVAL = svref;
290 OUTPUT:
291 RETVAL
292
293
294 ## T_AVREF
295
296 AV *
297 T_AVREF( av )
298 AV * av
299 CODE:
300 RETVAL = av;
301 OUTPUT:
302 RETVAL
303
304
305 ## T_AVREF_REFCOUNT_FIXED
306
307 AV_FIXED*
308 T_AVREF_REFCOUNT_FIXED( av )
309 AV_FIXED * av
310 CODE:
311 SvREFCNT_inc(av);
312 RETVAL = av;
313 OUTPUT:
314 RETVAL
315
316
317 ## T_HVREF
318
319 HV *
320 T_HVREF( hv )
321 HV * hv
322 CODE:
323 RETVAL = hv;
324 OUTPUT:
325 RETVAL
326
327
328 ## T_HVREF_REFCOUNT_FIXED
329
330 HV_FIXED*
331 T_HVREF_REFCOUNT_FIXED( hv )
332 HV_FIXED * hv
333 CODE:
334 SvREFCNT_inc(hv);
335 RETVAL = hv;
336 OUTPUT:
337 RETVAL
338
339
340 ## T_CVREF
341
342 CV *
343 T_CVREF( cv )
344 CV * cv
345 CODE:
346 RETVAL = cv;
347 OUTPUT:
348 RETVAL
349
350
351 ## T_CVREF_REFCOUNT_FIXED
352
353 CV_FIXED *
354 T_CVREF_REFCOUNT_FIXED( cv )
355 CV_FIXED * cv
356 CODE:
357 SvREFCNT_inc(cv);
358 RETVAL = cv;
359 OUTPUT:
360 RETVAL
361
362
363 ## T_SYSRET
364
365 # Test a successful return
366
367 SysRet
368 T_SYSRET_pass()
369 CODE:
370 RETVAL = 0;
371 OUTPUT:
372 RETVAL
373
374 # Test failure
375
376 SysRet
377 T_SYSRET_fail()
378 CODE:
379 RETVAL = -1;
380 OUTPUT:
381 RETVAL
382
383 ## T_UV
384
385 unsigned int
386 T_UV( uv )
387 unsigned int uv
388 CODE:
389 RETVAL = uv;
390 OUTPUT:
391 RETVAL
392
393
394 ## T_IV
395
396 long
397 T_IV( iv )
398 long iv
399 CODE:
400 RETVAL = iv;
401 OUTPUT:
402 RETVAL
403
404
405 ## T_INT
406
407 intTINT
408 T_INT( i )
409 intTINT i
410 CODE:
411 RETVAL = i;
412 OUTPUT:
413 RETVAL
414
415
416 ## T_ENUM
417
418 # The test should return the value for SVt_PVHV.
419 # 11 at the present time but we can't not rely on this
420 # for testing purposes.
421
422 svtype
423 T_ENUM()
424 CODE:
425 RETVAL = SVt_PVHV;
426 OUTPUT:
427 RETVAL
428
429
430 ## T_BOOL
431
432 bool
433 T_BOOL( in )
434 bool in
435 CODE:
436 RETVAL = in;
437 OUTPUT:
438 RETVAL
439
440 bool
441 T_BOOL_2( in )
442 bool in
443 CODE:
444 PERL_UNUSED_VAR(RETVAL);
445 OUTPUT:
446 in
447
448 void
449 T_BOOL_OUT( out, in )
450 bool out
451 bool in
452 CODE:
453 out = in;
454 OUTPUT:
455 out
456
457 ## T_U_INT
458
459 intUnsigned
460 T_U_INT( uint )
461 intUnsigned uint
462 CODE:
463 RETVAL = uint;
464 OUTPUT:
465 RETVAL
466
467
468 ## T_SHORT
469
470 short
471 T_SHORT( s )
472 short s
473 CODE:
474 RETVAL = s;
475 OUTPUT:
476 RETVAL
477
478
479 ## T_U_SHORT
480
481 U16
482 T_U_SHORT( in )
483 U16 in
484 CODE:
485 RETVAL = in;
486 OUTPUT:
487 RETVAL
488
489
490 ## T_LONG
491
492 intTLONG
493 T_LONG( in )
494 intTLONG in
495 CODE:
496 RETVAL = in;
497 OUTPUT:
498 RETVAL
499
500 ## T_U_LONG
501
502 U32
503 T_U_LONG( in )
504 U32 in
505 CODE:
506 RETVAL = in;
507 OUTPUT:
508 RETVAL
509
510
511 ## T_CHAR
512
513 char
514 T_CHAR( in );
515 char in
516 CODE:
517 RETVAL = in;
518 OUTPUT:
519 RETVAL
520
521
522 ## T_U_CHAR
523
524 unsigned char
525 T_U_CHAR( in );
526 unsigned char in
527 CODE:
528 RETVAL = in;
529 OUTPUT:
530 RETVAL
531
532
533 ## T_FLOAT
534
535 float
536 T_FLOAT( in )
537 float in
538 CODE:
539 RETVAL = in;
540 OUTPUT:
541 RETVAL
542
543
544 ## T_NV
545
546 NV
547 T_NV( in )
548 NV in
549 CODE:
550 RETVAL = in;
551 OUTPUT:
552 RETVAL
553
554
555 ## T_DOUBLE
556
557 double
558 T_DOUBLE( in )
559 double in
560 CODE:
561 RETVAL = in;
562 OUTPUT:
563 RETVAL
564
565
566 ## T_PV
567
568 char *
569 T_PV( in )
570 char * in
571 CODE:
572 RETVAL = in;
573 OUTPUT:
574 RETVAL
575
576 char *
577 T_PV_null()
578 CODE:
579 RETVAL = NULL;
580 OUTPUT:
581 RETVAL
582
583
584 ## T_PTR
585
586 # Pass in a value. Store the value in some static memory and
587 # then return the pointer
588
589 void *
590 T_PTR_OUT( in )
591 int in;
592 CODE:
593 xst_anint = in;
594 RETVAL = &xst_anint;
595 OUTPUT:
596 RETVAL
597
598 # pass in the pointer and return the value
599
600 int
601 T_PTR_IN( ptr )
602 void * ptr
603 CODE:
604 RETVAL = *(int *)ptr;
605 OUTPUT:
606 RETVAL
607
608
609 ## T_PTRREF
610
611 # Similar test to T_PTR
612 # Pass in a value. Store the value in some static memory and
613 # then return the pointer
614
615 intRef *
616 T_PTRREF_OUT( in )
617 intRef in;
618 CODE:
619 xst_anintref = in;
620 RETVAL = &xst_anintref;
621 OUTPUT:
622 RETVAL
623
624 # pass in the pointer and return the value
625
626 intRef
627 T_PTRREF_IN( ptr )
628 intRef * ptr
629 CODE:
630 RETVAL = *ptr;
631 OUTPUT:
632 RETVAL
633
634
635 ## T_PTROBJ
636
637 # Similar test to T_PTRREF
638 # Pass in a value. Store the value in some static memory and
639 # then return the pointer
640
641 intObj *
642 T_PTROBJ_OUT( in )
643 intObj in;
644 CODE:
645 xst_anintobj = in;
646 RETVAL = &xst_anintobj;
647 OUTPUT:
648 RETVAL
649
650 # pass in the pointer and return the value
651
652 MODULE = XS::Typemap PACKAGE = intObjPtr
653
654 intObj
655 T_PTROBJ_IN( ptr )
656 intObj * ptr
657 CODE:
658 RETVAL = *ptr;
659 OUTPUT:
660 RETVAL
661
662 MODULE = XS::Typemap PACKAGE = XS::Typemap
663
664
665 ## T_REF_IV_REF
666 ## NOT YET
667
668
669 ## T_REF_IV_PTR
670
671 # Similar test to T_PTROBJ
672 # Pass in a value. Store the value in some static memory and
673 # then return the pointer
674
675 intRefIv *
676 T_REF_IV_PTR_OUT( in )
677 intRefIv in;
678 CODE:
679 xst_anintrefiv = in;
680 RETVAL = &xst_anintrefiv;
681 OUTPUT:
682 RETVAL
683
684 # pass in the pointer and return the value
685
686 MODULE = XS::Typemap PACKAGE = intRefIvPtr
687
688 intRefIv
689 T_REF_IV_PTR_IN( ptr )
690 intRefIv * ptr
691 CODE:
692 RETVAL = *ptr;
693 OUTPUT:
694 RETVAL
695
696
697 MODULE = XS::Typemap PACKAGE = XS::Typemap
698
699 ## T_PTRDESC
700 ## NOT YET
701
702
703 ## T_REFREF
704 ## NOT YET
705
706
707 ## T_REFOBJ
708 ## NOT YET
709
710
711 ## T_OPAQUEPTR
712
713 intOpq *
714 T_OPAQUEPTR_IN( val )
715 intOpq val
716 CODE:
717 xst_anintopq = val;
718 RETVAL = &xst_anintopq;
719 OUTPUT:
720 RETVAL
721
722 intOpq
723 T_OPAQUEPTR_OUT( ptr )
724 intOpq * ptr
725 CODE:
726 RETVAL = *ptr;
727 OUTPUT:
728 RETVAL
729
730 short
731 T_OPAQUEPTR_OUT_short( ptr )
732 shortOPQ * ptr
733 CODE:
734 RETVAL = *ptr;
735 OUTPUT:
736 RETVAL
737
738 # Test it with a structure
739 astruct *
740 T_OPAQUEPTR_IN_struct( a,b,c )
741 int a
742 int b
743 double c
744 PREINIT:
745 struct t_opaqueptr test;
746 CODE:
747 test.a = a;
748 test.b = b;
749 test.c = c;
750 RETVAL = &test;
751 OUTPUT:
752 RETVAL
753
754 void
755 T_OPAQUEPTR_OUT_struct( test )
756 astruct * test
757 PPCODE:
758 XPUSHs(sv_2mortal(newSViv(test->a)));
759 XPUSHs(sv_2mortal(newSViv(test->b)));
760 XPUSHs(sv_2mortal(newSVnv(test->c)));
761
762
763 ## T_OPAQUE
764
765 shortOPQ
766 T_OPAQUE_IN( val )
767 int val
768 CODE:
769 RETVAL = (shortOPQ)val;
770 OUTPUT:
771 RETVAL
772
773 IV
774 T_OPAQUE_OUT( val )
775 shortOPQ val
776 CODE:
777 RETVAL = (IV)val;
778 OUTPUT:
779 RETVAL
780
781 array(int,3)
782 T_OPAQUE_array( a,b,c)
783 int a
784 int b
785 int c
786 PREINIT:
787 int array[3];
788 CODE:
789 array[0] = a;
790 array[1] = b;
791 array[2] = c;
792 RETVAL = array;
793 OUTPUT:
794 RETVAL
795
796
797 ## T_PACKED
798
799 void
800 T_PACKED_in(in)
801 anotherstruct *in;
802 PPCODE:
803 mXPUSHi(in->a);
804 mXPUSHi(in->b);
805 mXPUSHn(in->c);
806 Safefree(in);
807 XSRETURN(3);
808
809 anotherstruct *
810 T_PACKED_out(a, b ,c)
811 int a;
812 int b;
813 double c;
814 CODE:
815 Newxz(RETVAL, 1, anotherstruct);
816 RETVAL->a = a;
817 RETVAL->b = b;
818 RETVAL->c = c;
819 OUTPUT: RETVAL
820 CLEANUP:
821 Safefree(RETVAL);
822
823 ## T_PACKEDARRAY
824
825 void
826 T_PACKEDARRAY_in(in)
827 anotherstruct **in;
828 PREINIT:
829 unsigned int i = 0;
830 PPCODE:
831 while (in[i] != NULL) {
832 mXPUSHi(in[i]->a);
833 mXPUSHi(in[i]->b);
834 mXPUSHn(in[i]->c);
835 ++i;
836 }
837 XS_release_anotherstructPtrPtr(in);
838 XSRETURN(3*i);
839
840 anotherstruct **
841 T_PACKEDARRAY_out(...)
842 PREINIT:
843 unsigned int i, nstructs, count_anotherstructPtrPtr;
844 CODE:
845 if ((items % 3) != 0)
846 croak("Need nitems divisible by 3");
847 nstructs = (unsigned int)(items / 3);
848 count_anotherstructPtrPtr = nstructs;
849 Newxz(RETVAL, nstructs+1, anotherstruct *);
850 for (i = 0; i < nstructs; ++i) {
851 Newxz(RETVAL[i], 1, anotherstruct);
852 RETVAL[i]->a = SvIV(ST(3*i));
853 RETVAL[i]->b = SvIV(ST(3*i+1));
854 RETVAL[i]->c = SvNV(ST(3*i+2));
855 }
856 OUTPUT: RETVAL
857 CLEANUP:
858 XS_release_anotherstructPtrPtr(RETVAL);
859
860
861 ## T_DATAUNIT
862 ## NOT YET
863
864
865 ## T_CALLBACK
866 ## NOT YET
867
868
869 ## T_ARRAY
870
871 # Test passes in an integer array and returns it along with
872 # the number of elements
873 # Pass in a dummy value to test offsetting
874
875 # Problem is that xsubpp does XSRETURN(1) because we arent
876 # using PPCODE. This means that only the first element
877 # is returned. KLUGE this by using CLEANUP to return before the
878 # end.
879 # Note: I read this as: The "T_ARRAY" typemap is really rather broken,
880 # at least for OUTPUT. That is apart from the general design
881 # weaknesses. --Steffen
882
883 intArray *
884 T_ARRAY( dummy, array, ... )
885 int dummy = 0;
886 intArray * array
887 PREINIT:
888 U32 size_RETVAL;
889 CODE:
890 dummy += 0; /* Fix -Wall */
891 size_RETVAL = ix_array;
892 RETVAL = array;
893 OUTPUT:
894 RETVAL
895 CLEANUP:
896 Safefree(array);
897 XSRETURN(size_RETVAL);
898
899
900 ## T_STDIO
901
902 FILE *
903 T_STDIO_open( file )
904 const char * file
905 CODE:
906 RETVAL = xsfopen( file );
907 OUTPUT:
908 RETVAL
909
910 void
911 T_STDIO_open_ret_in_arg( file, io)
912 const char * file
913 FILE * io = NO_INIT
914 CODE:
915 io = xsfopen( file );
916 OUTPUT:
917 io
918
919 SysRet
920 T_STDIO_close( f )
921 PerlIO * f
922 PREINIT:
923 FILE * stream;
924 CODE:
925 /* Get the FILE* */
926 stream = PerlIO_findFILE( f );
927 /* Release the FILE* from the PerlIO system so that we do
928 not close the file twice */
929 PerlIO_releaseFILE(f,stream);
930 /* Must release the file before closing it */
931 RETVAL = xsfclose( stream );
932 OUTPUT:
933 RETVAL
934
935 int
936 T_STDIO_print( stream, string )
937 FILE * stream
938 const char * string
939 CODE:
940 RETVAL = xsfprintf( stream, string );
941 OUTPUT:
942 RETVAL
943
944
945 ## T_INOUT
946
947 PerlIO *
948 T_INOUT(in)
949 PerlIO *in;
950 CODE:
951 RETVAL = in; /* silly test but better than nothing */
952 OUTPUT: RETVAL
953
954
955 ## T_IN
956
957 inputfh
958 T_IN(in)
959 inputfh in;
960 CODE:
961 RETVAL = in; /* silly test but better than nothing */
962 OUTPUT: RETVAL
963
964
965 ## T_OUT
966
967 outputfh
968 T_OUT(in)
969 outputfh in;
970 CODE:
971 RETVAL = in; /* silly test but better than nothing */
972 OUTPUT: RETVAL
973
974