[FFmpeg-devel] [PATCH v2 1/2] avutil/wchar_filename, file_open: Support long file names on Windows

Soft Works softworkz at hotmail.com
Tue May 24 12:47:37 EEST 2022



> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces at ffmpeg.org> On Behalf Of Soft
> Works
> Sent: Monday, May 23, 2022 5:48 PM
> To: FFmpeg development discussions and patches <ffmpeg-devel at ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v2 1/2] avutil/wchar_filename,
> file_open: Support long file names on Windows
> 
> 
> 
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces at ffmpeg.org> On Behalf Of nil-
> > admirari at mailo.com
> > Sent: Monday, May 23, 2022 5:36 PM
> > To: ffmpeg-devel at ffmpeg.org
> > Subject: Re: [FFmpeg-devel] [PATCH v2 1/2] avutil/wchar_filename,
> > file_open: Support long file names on Windows
> >
> > >> Not possible for stat precisely because of function and struct
> sharing
> > a
> > >> name.
> >
> > > That's exactly what is said above and before :-)
> >
> > My previous question was not answered, so I had to look up the answer
> > myself.
> >
> > > I'm actually wondering how does it even compile. All stat structs in
> > code
> > > become struct win32_stat, and all calls to stat become calls to
> > win32_stat,
> > > which in turn wraps _wstati64. But _wstati64 does not accept struct
> > win32_stat*,
> > > it accepts struct _stati64*. Content of these structs is probably
> > identical, but
> > > it should not matter: C is typed nominally, not structurally.
> >
> > Turns out C actually has a concept of compatible types:
> > https://en.cppreference.com/w/c/language/type.
> >
> > The problems is:
> > > they are both structure/union/enumeration types, and
> > > - (c99) if one is declared with a tag, the other must also be declared
> > with the same tag.
> > > ...
> > > If two declarations refer to the same object or function and do not
> use
> > compatible types,
> > > the behavior of the program is undefined.
> >
> > Your structure does not have the same tag as the CRT's one.
> > Are you sure you want to rely on undefined behaviour?
> >
> > I haven't compiled your code, but the following simple example:
> >
> > struct A { int a, b, c; };
> > struct B { int a, b, c; };
> > void printA(struct A *a);
> >
> > struct B b = { 1, 2, 3 };
> > printA(&b);
> >
> > generates a
> >
> > warning: passing argument 1 of ‘printA’ from incompatible pointer type
> [-
> > Wincompatible-pointer-types]
> >     |     printA(&b);
> >     |            ^~
> >     |            |
> >     |            struct B *
> > note: expected ‘struct A *’ but argument is of type ‘struct B *’
> >     | void printA(struct A *a)
> >
> > Are you sure you wanna add a couple of similar warnings to the project?
> 
> This is not what's happening. No warnings, not even from clang diagnostics
> with -Weverything.

I'm sorry, you were right and I was wrong. The includes and macros had hidden
away all the warnings.

For my new solution which I had submitted today, I had made a test in a code
file where I put all the new things directly and expanded the macros.

This gives in fact the kind of error you mentioned:

... function': incompatible types - from 'win32_stat *' to '_stat64 *'


I had explained the way it works to Martin in another response. The 
relevant part is:

The struct:

    struct win32_stat
    {
        struct _stati64;
    };

makes use of a MS compiler feature called "anonymous structures":
This way, we automatically "inherit" the members of the struct.

Now, that still gives the incompatible type warning. 

If we would
want to get rid of this, we could define the struct as follows:


    struct win32_stat
    {
        union
        {
            struct _stati64;
            struct _stati64 stat;
        };
    };

The union is anonymous and includes _stati64 twice: once anonymous
and once named.

This would allow us to define our win32_stat function like this:


static inline int win32_stat(const char *filename_utf8, struct win32_stat *par)
{
    wchar_t *filename_w;
    int ret;
    if (get_extended_win32_path(filename_utf8, &filename_w))
        return -1;
    if (!filename_w)
        goto fallback;
    ret = _wstat64(filename_w, &par->stat);
    av_free(filename_w);
    return ret;
fallback:
      return _stat64(filename_utf8, &par->stat);
}

so it uses the ->stat member for doing the api calls while
the calling (ffmpeg) code can use the structure as if it was the 
actual POSIX stat structure.


Kind regards,
sw







More information about the ffmpeg-devel mailing list