How to avoid IF

25 views
Skip to first unread message

Chris Barker

unread,
Mar 13, 2024, 7:17:58 PMMar 13
to cython-users
So apparently IF has been deprecated:

The 'IF' statement is deprecated and will be removed in a future Cython version. Consider using runtime conditions or C macros instead. See https://github.com/cython/cython/issues/4310
However, I followed that link, and a link to docs, and I can't figure out how to do conditional compilation any other way. The problem at hand is a function that opens a file, returning a FILE pointer. Windows has its own way of dealing with filename (wchar_t), so having figure that out, I now have this:

cdef FILE* open_file(file_path) except *:
    """
    opens a file for writing

    :param path: python str or PathLike

    :returns: File Pointer

    Note: On Windows, it uses a wchar, UTC-16 encoded
          On other platforms (Mac and Linux), it assumes utf-8.

          If the file system is not utf-8 encoded, this will only
          work for ascii file paths.
    """
    cdef FILE* fp = NULL

    file_path = os.fspath(file_path)

    IF UNAME_SYSNAME == 'Windows':
        cdef Py_ssize_t length
        cdef wchar_t *wchar_flag = PyUnicode_AsWideCharString("wb", &length)
        cdef wchar_t *wchar_filepath = PyUnicode_AsWideCharString(file_path, &length)

        fp = _wfopen(wchar_filepath, wchar_flag)

        PyMem_Free(<void *>wchar_filepath)
        PyMem_Free(<void *>wchar_flag)
    ELSE:
        fp = fopen(file_path.encode('utf-8'), "wb")

    if fp is NULL:
        raise OSError('could not open the file: {}'.format(file_path))

    return fp

So how do I not use IF for that? I'm not completely sure if wchar_t is available on other platforms, but I;m sure  that _wfopen is not. So I can't use run-time checking .. any ideas?

Thanks,

-CHB



--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris....@noaa.gov

Oscar Benjamin

unread,
Mar 13, 2024, 7:29:03 PMMar 13
to cython...@googlegroups.com
You can do this at C preprocessor level with cdef extern from * and
then "import" it into Cython e.g.:

https://github.com/flintlib/python-flint/blob/1ce152dffc356af69b1d4c2ea0eb08854f3d733b/src/flint/flintlib/fmpz_mod_mat.pxd#L21-L102

For your case that would be something like

cdef extern from *
"""
#if WINDOWS /* Not sure what variable to check here */
FILE* myfunc() { stuff... }
#else
FILE* myfunc() { other stuff ...}
#endif
"""

cdef extern from somewhere:
FILE* myfunc()

The first part adds preprocessor defines to the generated C code. The
second part convinces Cython that a C-level function called myfunc
with the given signature exists somewhere in the C code.

If anyone knows a better way then I'm also interested...

--
Oscar
Reply all
Reply to author
Forward
0 new messages