Nick Ing-Simmons wrote:

Steve Hay <[EMAIL PROTECTED]> writes:

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.
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.)
Thanks once again for the excellent reply!

My wrapper function now looks broadly like:

FILE *f;
PerlIO *p;

f = library_func(file, mode);

// Force binary mode for underlying FILE *.
PerlLIO_setmode(PerlSIO_fileno(f), O_BINARY);

// Import FILE * to PerlIO *.
p = PerlIO_importFILE(f, mode);

// Push translation layer on PerlIO if required.
if (strchr(mode, 'b') == NULL)
PerlIO_binmode(p, type, O_TEXT, ":crlf");

// Now store PerlIO in used-supplied glob ref...

This works perfectly under my Perl without PERL_IMPLICIT_SYS enabled (including the example quoted above), but I still have the same problem with PerlIO_binmode() that I reported previously when building against a Perl with PERL_IMPLICIT_SYS enabled: "different types for formal and actual parameter" 1, 2 and 4, and "too few actual parameters".

I'm still not sure I understood what you said earlier on this point. You mentioned a perlsio_binmode() function in "perlio.c", but that operates on a FILE *, not a PerlIO * like I'm doing here, so I wouldn't want to use it here even if it was exported as PerlSIO_binmode().

Why does the PerlIO_binmode() in the outline of my wrapper function above cause a problem? Is it something that I'm doing wrong, or a teething problem with stdio/PerlIO co-existence in ActivePerl that I can't do anything about in my code?

- Steve

Reply via email to