Some elaboration on calling conventions

Hello,

I’m curious about the calling conventions of C functions. I’m currently playing with a project based on the SDL3 library. The library supports the macro SDLCALL. The macro is used with a function declaration and its purpose to set the function declaration to cdecl if the library targets Windows. Here’s the snippet of the macro declaration

#ifndef SDLCALL
#if defined(SDL_PLATFORM_WINDOWS) && !defined(__GNUC__)
#define SDLCALL __cdecl
#else
#define SDLCALL
#endif
#endif /* SDLCALL */

An example of how the macro is used:

void SDLCALL myfunc(void) {}

Given that, I’ve been wondering how I define functions with the macro in Zig. Is the following definition equivalent?

fn myfunc() callconv(.C) void { }

Best,
Alex Markov

In this case I think it should be the same, depending of how SDL_PLATFORM_WINDOWS is defined. In general you can find some more information in std.builtin.CallingConvention there is this:

    /// This is an alias for the default C calling convention for this target.
    /// Functions marked as `extern` or `export` are given this calling convention by default.
    pub const c = builtin.target.cCallingConvention().?;

Microsoft docs state that __cdecl is the windows default calling convention, so I would assume whatever zig uses as C conv on Windows is equivalent, looking at the code they have a _win suffix in all cases where os == windows is checked.

There is also x86_16_cdecl, the only one that has cdecl in its name. I assume that’s because it’s the only cdecl conv that is used outside of windows, given that it is the C callconv on all x86_16 platforms.

Sources are std.builtin.CallingConvention, .C is an alias, the value of which is computed by std.Target.cCallingConvention.

(on master, btw, it’s .c and is (usually? always?) a decl literal, to keep parity with other enum casing norms)

1 Like

The part “Microsoft docs state” allowed to make a search query which answered the part of the question which I omitted from my question. I asked only about __cdecl to keep the question specific. However, I hid in mind a part with the made up term “custom calling convention”. I was curious how I use them with Zig compiler, given that the builtin provides a finite number of calling conventions. Now, I realize:

  1. a calling convention is defined by the platform;
  2. in x64 world they are nearly obsolete;
  3. a custom calling convention is something which might appear with a custom platform;
  4. Zig compiler implements all of the calling conventions I found popular;

I wasn’t able to make a right search query without your answers. Many thanks!

1 Like