Re: cannot open file if name contains accented characters

Mátyás Seress <[email protected]>
Newsgroups gmane.lisp.scheme.chicken
Message-ID <CAAQd4poKGQwaX344Zb4+hLAcDZPO5=e0HnfC=CMvV-3fOd=jOQ@mail.gmail.com>
I tried your code but I got all kinds of compile errors. Sorry, but it's
gotten to be too much effort to just open a file.

Op di 26 dec 2023 om 21:45 schreef <[email protected]>:

> > Thanks for the responses. I tried what I could, but it still doesn't
> work.
> > I wrote some code to test if I can open and close a file. The C code
> works
> > but the Chicken code doesn't.
> >
> > (import (chicken foreign))
> >
> > (foreign-declare "#include <stdio.h>")
> > (foreign-declare "#include <wchar.h>")
> >
> > (define chicken_wfopen
> >     (foreign-lambda (c-pointer "FILE") "_wfopen" (c-pointer "wchar_t")
> > (c-pointer "wchar_t")))
> > (define chicken_fclose
> >     (foreign-lambda int "fclose" (c-pointer "FILE")))
> >
> > (let ([file-handle (chicken_wfopen "c:\\temp\\íűőúöüóéá.txt" "r")])
> >     (print "File has been opened at: " (number->string file-handle))
> >     (print "Closing file.")
> >     (chicken_fclose file-handle))
> >
> > The Chicken code fails with the error message: Error: unbound variable:
> > It doesn't say the name of the variable, and it returns the error code
> 70.
> > Note that in C the string needs to be prefixed with an L to make it wide
> > character. In Chicken I don't know how to do that.
> > Does anybody have a clue which variable is unbound?
>
> Ugh. Sorry, I don't know what variable is meant here. I also gave wrong
> information: _wfopen returns a FILE* (as you correctly implement above).
> The returned pointer will not be a number, though.
>
> Anyway: the strings you pass are Scheme strings, passes as char *
> to the FFI code, this is wrong, as you want UTF-16 Windows strings
> (wchar_t *) here. The proper way would be (I think) to do
>
> ;; warning: totally untested
>
> (define wfopen
>   (foreign-lambda* bool ((c-string str) (c-string mode) (scheme-object
> port))
>    "int sz1 = 4 * (strlen(str) + 1), sz2 = 4 * (strlen(mode) + 1);
>      wchar_t *buf1 = malloc(sz1), buf2 = malloc(sz2);
>      FILE *fp;
>      MultiByteToWideChar(CP_UTF8, 0, str, -1, buf1, sz1);
>      MultiByteToWideChar(CP_UTF8, 0, mode, -1, buf2, sz2);
>      fp = _wfopen(buf1, buf2);
>      free(buf1); free(buf2);
>      if(fp == NULL) return(0);
>      C_set_block_item(port, 0, (C_word)fp);
>      return(1);"))
>
> (define (fopen-utf16 fname mode input?)
>   (let ((p (##sys#make-port (if input? 1 2) ##sys#stream-port-class name
> 'stream)))
>     (if (wfopen fname mode)
>         p
>         (error "error opening file" fname mode))))
>
> the ##sys#make-port thing above creates a proper port to be used in Scheme,
> the input? flag is unfortunately needed to distinguish between input and
> output
> ports. Sorry if all this is a bit confusing.
>
>
> felix
>
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.