Steve Hay <[EMAIL PROTECTED]> writes:
>>Did you pass in the correct "mode" ?
>> e.g. PerlIO_importFILE(f,"wt");
>>
>>It is _possible_ that if PerlIO is told file is in text mode 
>>it may actually act on a PerlIO_binmode() to put in into binary.
>>But I had not thought of that case so if it works it is just 
>>due to "regular" coding ...
>>
>I wasn't specifying the mode, but I am now and, alas, it makes no 
>difference.

I was afraid it wasn't.

>>
>>Open the FILE * as binary in the XS code before importing it?
>>
>Unfortunately, this is not an option for me.

Yes it is - see below...

>
>The situation that I really have is this:
>
>I am writing a Perl interface to C library function that returns a FILE 
>*.  The end user can specify the text/binary mode in the call to the C 
>library function (and my Perl wrapper), and, as with most file-open 
>functions on Windows, the mode defaults to "text" if it is not specified.
>
>I found that if the file is opened in "text" mode (either explicitly, or 
>by default) then the end user cannot subsequently change to "binary" 
>mode.  For example, this doesn't work as expected:
>
>    my $fh = gensym();
>    my_wrapper_func($fh, $file, "w");
>    binmode $fh;

Suggestion: 
     In XS code for my_wrapper_func() check the mode string
     user passed and append a "b" if not already there.
     Call real function.
     If user did NOT pass "b" call PerlIO_binmode() to set PerlIO to text mode. 
>
>Admittedly, the end user can remedy this by simply calling 
>my_wrapper_func($fh, $file, "wb") to start with, but I regarded the 
>above as a bug that really ought to be fixed anyway.  

Agreed (up to a point) but that isn't going to be immediate.

>The same idiom 
>works fine with the Perl builtin functions open() and sysopen(), and is 
>more portable than explicitly specifying the mode as "wb" because not 
>all systems understand such mode strings, so why should my function have 
>to be any different?

A. All ANSI C systems are supposed to understand such strings.
B. Your code isn't any different - PerlIO has to jump through hoops
   to make FILE */binmode work, so does you XS code ;-)

>
>My wrapper works by calling the C library function to get a FILE *, then 
>imports it to a PerlIO * which it stores in the glob reference that the 
>end user has passed in.  It was only in trying to fix this "bug" that I 
>started looking at whether PerlIO_binmode() worked, since that is what 
>the Perl builtin binmode() function uses: I wondered whether my problem 
>was with binmode() or with PerlIO_binmode().
>
>How do I get the above example to work, or can't I?

See suggestion above.

>
>BTW, my module also wraps an analogous low-io level function in a 
>similar way, and has no such problems.  My wrapper calls the library 
>function to get an int file descriptor, imports it to a PerlIO * by 
>calling PerlIO_fdopen() (also not specifying the mode) and stores it on 
>the glob reference passed in.  If the end user opens the file in text 
>mode initially and then tries switching to binary mode then it does work 
>fine!
>
>What's the difference?

I don't know for sure - but nore that PerlIO_fdopen() also does some 
hoop jumping.

>>Same kind of mess that you had with your other questions.
>>There is:
>>
>>int perlsio_binmode(FILE *fp, int iotype, int mode);
>>
>>in the non-PerlIO body of perlio.c
>>
>>Which should probably have been exported via PerlSIO_binmode().
>>
>I'm not sure about this.  The mess that I had before arose from using 
>fclose() under PERL_IMPLICIT_SYS: you pointed out that for access to the 
>original stdio function I should be using PerlSIO_fclose() instead.

And now you could be calling system's stdio binmode()/setmode

>
>But in this case, I'm calling PerlIO_binmode() on a __PerlIO *__ -- I'm 
>not after access to an original stdio function, so I wouldn't expect to 
>be using a PerlSIO_*() function.
>
>I can easily set the FILE * to "binary" mode before importing to a 
>PerlIO * by calling:
>
>    setmode(PerlSIO_fileno(f), O_BINARY)
>
>and this does work, but, as outlined above, it is not really what I'm after.
Why not just insert that in your wrapper before calling importFILE?
(That is likely to be how I "fix" this in 5.8.1 - do a setmode() inside 
importFILE and then push a CRLF layer above stdio if stream was in text mode.) 

However that is way PerlIO is architected in 5.8.0 - low level files 
are binary ON ALL PLATFORMS and any CRLF, Encoding etc. translations 
are done in extra layers on top of that.

This helps portability in that a script on any platform can 
read/write any kind of file.

-- 
Nick Ing-Simmons
http://www.ni-s.u-net.com/

Reply via email to