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 <felix.winkelm...@bevuta.com>:

> > 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
>
>
>

Reply via email to