Nick Ing-Simmons wrote:
Steve Hay <[EMAIL PROTECTED]> writes:I wasn't specifying the mode, but I am now and, alas, it makes no difference.
I call PerlIO_importFILE() to get a PerlIO *, then call: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 ...
Unfortunately, this is not an option for me.PerlIO_binmode(p, type, O_BINARY, Nullch)PerlIO_binmode puts PerlIO into binmode ;-) Your problem is that the underlying FILE * is translating.
to put the file handle into "binary mode", and then call PerlIO_printf() and PerlIO_close(). The data printed to this file handle was "Hello, world.\n", but when I look at the file that has been created it ends with "\r\n" -- i.e. "text mode" translation has been performed on the data. This was not what I expected. Have I mis-interpreted what the PerlIO_binmode() call is supposed to do, or is this broken?
When PerlIO uses stdio (and it does NOT by default on Win32) it always
opens FILE * as binary.
Is this all something to do with the new PerlIO "layers"? Am I simply adding more layers to the existing "text mode" layer? If so, then how do I remove that existing layer so that the file handle is (just) "binary mode"?
Open the FILE * as binary in the XS code before importing it?
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;
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. 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?
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?
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'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.The above all relates to a Perl that I've built myself (without PERL_IMPLICIT_SYS). If I try and use ActivePerl instead (which has PERL_IMPLICIT_SYS) then the module won't even build:
Why is this?
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().
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.
Cheers,
Steve
