Skip to content

Commit

Permalink
Patch edflib.c on Windows to enable opening UTF-8 encoded paths
Browse files Browse the repository at this point in the history
This should fix file opening issue with non-ASCII characters in paths
when local encoding is not UTF-8.
  • Loading branch information
myd7349 committed Sep 4, 2023
1 parent 1af9ced commit 475a100
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pip-log.txt
# Project working files
_edflib.[ch]
_pyedflib.[ch]
edflib_utf8.c

edf.[ch]
cythonize.dat
Expand Down
57 changes: 57 additions & 0 deletions pyedflib/_extensions/c/fopen_utf8.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#ifdef _WIN32

#include "fopen_utf8.h"

#include <stdlib.h>
#include <windows.h>


wchar_t* utf8_to_utf16(const char* str)
{
wchar_t* wstr;

int require = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (require == 0)
return NULL;

wstr = malloc(require * sizeof(wchar_t));
if (wstr == NULL)
return NULL;

if (MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, require) == 0)
{
free(wstr);
return NULL;
}

return wstr;
}


FILE* fopen_utf8(const char* filename, const char* mode)
{
errno_t error;
FILE* file;
wchar_t* wfilename;
wchar_t* wmode;

wfilename = utf8_to_utf16(filename);
if (wfilename == NULL)
return NULL;

wmode = utf8_to_utf16(mode);
if (wmode == NULL)
{
free(wfilename);
return NULL;
}

error = _wfopen_s(&file, wfilename, wmode);

free(wfilename);
free(wmode);

return error == 0 ? file : NULL;
}

#endif
20 changes: 20 additions & 0 deletions pyedflib/_extensions/c/fopen_utf8.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef FOPEN_UTF8_H_
#define FOPEN_UTF8_H_

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _WIN32
FILE* fopen_utf8(const char* filename, const char* mode);
#else
#define fopen_utf8 fopen
#endif

#ifdef __cplusplus
}
#endif

#endif
25 changes: 23 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,30 @@ def write_version_py(filename='pyedflib/version.py'):

make_ext_path = partial(os.path.join, "pyedflib", "_extensions")

sources = ["c/edflib.c"]
if os.name == "nt":
# Patch edflib.c
with open(make_ext_path("c/edflib.c"), "rb") as fin:
with open(make_ext_path("c/edflib_utf8.c"), "wb") as fout:
for line in fin:
line = line.replace(
b'#include "edflib.h"',
b'#include "edflib.h"\r\n#include "fopen_utf8.h"')
line = line.replace(
b'file = fopeno(path, "rb");',
b'file = fopen_utf8(path, "rb");')
line = line.replace(
b'file = fopeno(path, "wb");',
b'file = fopen_utf8(path, "wb");')

fout.write(line)

sources = ["c/edflib_utf8.c", "c/fopen_utf8.c"]
headers = ["c/edflib.h", "c/fopen_utf8.h"]
else:
sources = ["c/edflib.c"]
headers = ["c/edflib.h"]

sources = list(map(make_ext_path, sources))
headers = ["c/edflib.h"]
headers = list(map(make_ext_path, headers))

cython_modules = ['_pyedflib']
Expand Down

0 comments on commit 475a100

Please sign in to comment.