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