Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C/C++ calling convention

4 views
Skip to first unread message

Stanisław Findeisen

unread,
Aug 24, 2010, 4:56:23 PM8/24/10
to
Given an architecture and a language (C or C++), is there any standard
function calling convention? Or is it compiler dependent?

Thanks!

STF

http://eisenbits.homelinux.net/~stf/
OpenPGP: DFD9 0146 3794 9CF6 17EA D63F DBF5 8AA8 3B31 FE8A

Ian Collins

unread,
Aug 24, 2010, 5:14:32 PM8/24/10
to
On 08/25/10 08:56 AM, Stanisław Findeisen wrote:
> Given an architecture and a language (C or C++), is there any standard
> function calling convention? Or is it compiler dependent?

The two languages are different. With C, there will be a platform
standard, with C++ it is still (regrettably) compiler specific.

--
Ian Collins

BGB / cr88192

unread,
Aug 24, 2010, 10:50:47 PM8/24/10
to

"Ian Collins" <ian-...@hotmail.com> wrote in message
news:8dir1p...@mid.individual.net...

> On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
>> Given an architecture and a language (C or C++), is there any standard
>> function calling convention? Or is it compiler dependent?
>
> The two languages are different. With C, there will be a platform
> standard, with C++ it is still (regrettably) compiler specific.
>

yep...

however, typically, C++ uses the same basic calling convention as C, but
usually differing only in that the C++ case tends to use a name-mangling
scheme (often compiler specific, but some "de-facto" conventions exist, for
example the use of MSVC-like conventions on Windows and the IA-64 ABI
name-mangling on Linux).

there does tend to be a difference in how compilers pass 'this', with some
compilers using an additional register (thiscall in MSVC), but more commonly
it is passed as a hidden first argument (although AFAIK usually after the
hidden first argument used for returning structs).


although, it is not really "safe" to rely on the specifics of any of this...

similarly, it is not really "safe" to use C++-based APIs across library
boundaries, nor for that matter to pass memory or file references between
DLL's (this leads to "fun" sometimes...).

for example, MSVC likes giving each DLL its own local C library, and hence,
its own local memory heap and set of open files, resulting in a few issues
which may pop up occassionally... (these issues don't tend to pop up with
MinGW or Cygwin, as these handle this situation differently...).

or such...


Ian Collins

unread,
Aug 24, 2010, 11:12:50 PM8/24/10
to
On 08/25/10 02:50 PM, BGB / cr88192 wrote:
> "Ian Collins"<ian-...@hotmail.com> wrote in message
> news:8dir1p...@mid.individual.net...
>> On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
>>> Given an architecture and a language (C or C++), is there any standard
>>> function calling convention? Or is it compiler dependent?
>>
>> The two languages are different. With C, there will be a platform
>> standard, with C++ it is still (regrettably) compiler specific.
>
> however, typically, C++ uses the same basic calling convention as C, but
> usually differing only in that the C++ case tends to use a name-mangling
> scheme (often compiler specific, but some "de-facto" conventions exist, for
> example the use of MSVC-like conventions on Windows and the IA-64 ABI
> name-mangling on Linux).
>
> there does tend to be a difference in how compilers pass 'this', with some
> compilers using an additional register (thiscall in MSVC), but more commonly
> it is passed as a hidden first argument (although AFAIK usually after the
> hidden first argument used for returning structs).
>
>
> although, it is not really "safe" to rely on the specifics of any of this...
>
> similarly, it is not really "safe" to use C++-based APIs across library
> boundaries, nor for that matter to pass memory or file references between
> DLL's (this leads to "fun" sometimes...).

That is very platform specific. Those restrictions don't apply to Unix
or Unix like systems.

--
Ian Collins

BGB / cr88192

unread,
Aug 24, 2010, 11:42:47 PM8/24/10
to

"Ian Collins" <ian-...@hotmail.com> wrote in message
news:8djg1i...@mid.individual.net...

yes, but code which works on both sets of systems may need to abide by these
seemingly arbitrary restrictions as well...


like, for example, I recently had to do a bit of "creative tweaking" to be
able to get one of Xiph.org's codecs (Tremor, which is a minimalist
OGG/Vorbis decoder) to build and work on Windows.

it was funny, the code touted about how pure ANSI C and portable it was, yet
I still encountered several instances of:
minor compiler extensions (things which could have easily been overlooked,
such as doing arithmetic on void pointers, ...);
it using autoconf, which is itself non-portable;
some C99 features, and using a header which doesn't exist on Windows
("sys/time.h"), ...

as well as me tearing out the autoconf (I tend to use Makefiles for
damn-near everything, personally finding this to work better in my case),
...

as well as adding in some stuff to allow it to work as a DLL, ...


so, yes, portability is relative...

one can write much code which works nearly everywhere else, but doesn't work
on Windows, and one can easily write code on Windows which doesn't work
anywhere else...


much the same as code which hemorages memory can't be expected to work well
on many embedded systems either (what?... this thing only has 64MB of RAM
and no swap?...).


Goran Pusic

unread,
Aug 25, 2010, 3:07:52 AM8/25/10
to
On Aug 24, 10:56 pm, Stanisław Findeisen <nore...@eisenbits.com>
wrote:

> Given an architecture and a language (C or C++), is there any standard
> function calling convention? Or is it compiler dependent?

As far as I know, and as far as the language is concerned, calling
convention is absolutely 100% compiler and underlying CPU architecture
dependent^^^. (Is there some standard-dratft-dwelling-newsgroupie to
refute/confirm this?). If you look at e.g. C99 standard draft (and I
doubt it's different for previous versions), you will find no
mentioning of "calling convention", no "cdecl" or whatever, no
nothing.

Goran.

Stanisław Findeisen

unread,
Aug 25, 2010, 3:42:17 AM8/25/10
to
On 2010-08-25 04:50, BGB / cr88192 wrote:
> "Ian Collins" <ian-...@hotmail.com> wrote in message
> news:8dir1p...@mid.individual.net...
>> On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
>>> Given an architecture and a language (C or C++), is there any standard
>>> function calling convention? Or is it compiler dependent?
>> The two languages are different. With C, there will be a platform
>> standard, with C++ it is still (regrettably) compiler specific.
>>
>
> yep...
>
> however, typically, C++ uses the same basic calling convention as C, but
> usually differing only in that the C++ case tends to use a name-mangling
> scheme (often compiler specific, but some "de-facto" conventions exist, for
> example the use of MSVC-like conventions on Windows and the IA-64 ABI
> name-mangling on Linux).
>
> there does tend to be a difference in how compilers pass 'this', with some
> compilers using an additional register (thiscall in MSVC), but more commonly
> it is passed as a hidden first argument (although AFAIK usually after the
> hidden first argument used for returning structs).

What exactly happens when you compile your C++ function with extern "C"
declaration? Is it compiled and linked as if it was a C function?

What if such a function throws an exception?

What calling convention is used when that function is being called from
C++ code (from the same, or another translation unit)?

What calling convention is used when that function calls some other
function (be it C, C++ or C++ with extern "C" declaration)? What if that
other function throws an exception?

I am mixing some C with C++, and would like the code to be portable.
However I only care about POSIX and GNU/Linux.

Ian Collins

unread,
Aug 25, 2010, 4:50:34 AM8/25/10
to
On 08/25/10 07:42 PM, Stanisław Findeisen wrote:
> On 2010-08-25 04:50, BGB / cr88192 wrote:
>> "Ian Collins"<ian-...@hotmail.com> wrote in message
>> news:8dir1p...@mid.individual.net...
>>> On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
>>>> Given an architecture and a language (C or C++), is there any standard
>>>> function calling convention? Or is it compiler dependent?
>>> The two languages are different. With C, there will be a platform
>>> standard, with C++ it is still (regrettably) compiler specific.
>>
>> however, typically, C++ uses the same basic calling convention as C, but
>> usually differing only in that the C++ case tends to use a name-mangling
>> scheme (often compiler specific, but some "de-facto" conventions exist, for
>> example the use of MSVC-like conventions on Windows and the IA-64 ABI
>> name-mangling on Linux).
>>
>> there does tend to be a difference in how compilers pass 'this', with some
>> compilers using an additional register (thiscall in MSVC), but more commonly
>> it is passed as a hidden first argument (although AFAIK usually after the
>> hidden first argument used for returning structs).
>
> What exactly happens when you compile your C++ function with extern "C"
> declaration? Is it compiled and linked as if it was a C function?

Not compiled (it is still C++), but it will have the same linkage as C
functions on the same platform.

> What if such a function throws an exception?

All bets are off.

> What calling convention is used when that function is being called from
> C++ code (from the same, or another translation unit)?

C++ will call it as it would any other C function.

> What calling convention is used when that function calls some other
> function (be it C, C++ or C++ with extern "C" declaration)? What if that
> other function throws an exception?

extern "C" has no effect here.

--
Ian Collins

Goran Pusic

unread,
Aug 25, 2010, 6:28:32 AM8/25/10
to
On Aug 25, 9:42 am, Stanisław Findeisen <nore...@eisenbits.com> wrote:
> On 2010-08-25 04:50, BGB / cr88192 wrote:
>
>
>
> > "Ian Collins" <ian-n...@hotmail.com> wrote in message

> >news:8dir1p...@mid.individual.net...
> >> On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
> >>> Given an architecture and a language (C or C++), is there any standard
> >>> function calling convention? Or is it compiler dependent?
> >> The two languages are different.  With C, there will be a platform
> >> standard, with C++ it is still (regrettably) compiler specific.
>
> > yep...
>
> > however, typically, C++ uses the same basic calling convention as C, but
> > usually differing only in that the C++ case tends to use a name-mangling
> > scheme (often compiler specific, but some "de-facto" conventions exist, for
> > example the use of MSVC-like conventions on Windows and the IA-64 ABI
> > name-mangling on Linux).
>
> > there does tend to be a difference in how compilers pass 'this', with some
> > compilers using an additional register (thiscall in MSVC), but more commonly
> > it is passed as a hidden first argument (although AFAIK usually after the
> > hidden first argument used for returning structs).
>
> What exactly happens when you compile your C++ function with extern "C"
> declaration? Is it compiled and linked as if it was a C function?

I'd say that for a given compiler (version) on a given platform,
there's no difference between a C and a C++ function, except that you
need extern "C" to turn off name mangling that happens with a C++
compiler. So that's why you have extern "C".

> What if such a function throws an exception?

You have a bug, one of invoking undefined behavior? You see, if a
function is a C one, idea is that you want to interface with C, who
knows not of exceptions.

> What calling convention is used when that function is being called from
> C++ code (from the same, or another translation unit)?

Should be OK (given correct exception safety, which you should not
care about since function is a "C" one, and C code can't throw; IOW,
don't do silly things).

> What calling convention is used when that function calls some other
> function (be it C, C++ or C++ with extern "C" declaration)? What if that
> other function throws an exception?

Apply transitivity here :-)

> I am mixing some C with C++, and would like the code to be portable.
> However I only care about POSIX and GNU/Linux.

If you are calling C from C++, you're fine. If vice-versa, wrap any
extern "C" C++ functions into a try/catch and convert exception into
an error-return. Easy.

However, "portability" is a big word when speaking about C and C++
languages :-). Practical advice: you won't get it until you compile
with several compilers/versions, for several hardware architectures
and underlying OS-es. Also, you will fail for considerations other
than what you have up until now ;-).

Goran.

James Kanze

unread,
Aug 25, 2010, 8:46:49 AM8/25/10
to

Maybe. Formally, the situation is the same for both languages;
the language standard doesn't address this issue, it is up to
the platforms. Practically, there are very few platforms which
don't have a standard function calling convention for C, and not
too many which have one for C++ (but I think Linux has one, and
Itanium based machines).

In practice, when writing C++, just having common calling
conventions isn't enough. You need compatible implementations
of the STL as well. And on many implementations (g++, VC++),
the actual implementation of the STL changes depending on
compiler options, and even compiling all of the code with the
same compiler is no guarantee---you have to be sure that all of
the significant options were the same as well.

--
James Kanze

James Kanze

unread,
Aug 25, 2010, 8:52:10 AM8/25/10
to
On Aug 25, 3:50 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "Ian Collins" <ian-n...@hotmail.com> wrote in message

> news:8dir1p...@mid.individual.net...

> > On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
> >> Given an architecture and a language (C or C++), is there any standard
> >> function calling convention? Or is it compiler dependent?

> > The two languages are different. With C, there will be a platform
> > standard, with C++ it is still (regrettably) compiler specific.

> yep...

> however, typically, C++ uses the same basic calling convention as C, but
> usually differing only in that the C++ case tends to use a name-mangling
> scheme (often compiler specific, but some "de-facto" conventions exist, for
> example the use of MSVC-like conventions on Windows and the IA-64 ABI
> name-mangling on Linux).

How can it? Things like the layout of the vtable are part of
the calling conventions, and C++ can't possibly use the same
ones as C here.

> there does tend to be a difference in how compilers pass
> 'this', with some compilers using an additional register
> (thiscall in MSVC), but more commonly it is passed as a hidden
> first argument (although AFAIK usually after the hidden first
> argument used for returning structs).

Except on Intel, the first argument *is* usually in a register.

> although, it is not really "safe" to rely on the specifics of
> any of this...

> similarly, it is not really "safe" to use C++-based APIs
> across library boundaries, nor for that matter to pass memory
> or file references between DLL's (this leads to "fun"
> sometimes...).

That's not true, and I've done it on many platforms.

> for example, MSVC likes giving each DLL its own local C library,

MSVC does what you tell it in this regard. If you tell it to
give each DLL its own local C library, when you don't want to,
it's nobody's fault but your own.

> and hence, its own local memory heap and set of open files,
> resulting in a few issues which may pop up occassionally...
> (these issues don't tend to pop up with MinGW or Cygwin, as
> these handle this situation differently...).

I don't know about MinGW or Cygwin, but under most Unix, it's
also possible to arrange things so that each shared object has
its own free space arena as well, if this is what you want.

--
James Kanze

James Kanze

unread,
Aug 25, 2010, 8:55:35 AM8/25/10
to
On Aug 25, 4:12 am, Ian Collins <ian-n...@hotmail.com> wrote:
> On 08/25/10 02:50 PM, BGB / cr88192 wrote:

[...]


> > similarly, it is not really "safe" to use C++-based APIs
> > across library boundaries, nor for that matter to pass
> > memory or file references between DLL's (this leads to "fun"
> > sometimes...).

> That is very platform specific. Those restrictions don't
> apply to Unix or Unix like systems.

Which part of his statement are you referring to? It's not safe
to use C++ based APIs (with std::string, etc.) between code
compiled with different compiler options, with the same
compiler. And there's no problem passing memory or file
references between dynamically loaded object files on any of the
systems I've worked on, Windows or Unix. (We do it all the time
under Windows, here, and we did it regularly under Solaris and
Linux where I was before.)

--
James Kanze

James Kanze

unread,
Aug 25, 2010, 9:25:27 AM8/25/10
to
On Aug 25, 11:28 am, Goran Pusic <gor...@cse-semaphore.com> wrote:
> On Aug 25, 9:42 am, Stanis³aw Findeisen <nore...@eisenbits.com> wrote:

[...]


> I'd say that for a given compiler (version) on a given platform,
> there's no difference between a C and a C++ function, except that you
> need extern "C" to turn off name mangling that happens with a C++
> compiler. So that's why you have extern "C".

And you'd be wrong. At least one compiler I've used used
different calling conventions for C and for C++.

--
James Kanze

Goran Pusic

unread,
Aug 25, 2010, 9:39:20 AM8/25/10
to

Ugh. Which one and why (if you can be bothered)?

To be honest, I can't think of a reason why would any compiler match
calling conventions betwen C and C++, but that seems a most reasonable
(only sensible, really) thing to do when using extern "C".

Goran.

Stanisław Findeisen

unread,
Aug 25, 2010, 10:18:29 AM8/25/10
to

But calling convention is part of the function machine code, isn't it?
So I guess this is generated in compilation phase...

>> What if such a function throws an exception?
>
> All bets are off.
>
>> What calling convention is used when that function is being called from
>> C++ code (from the same, or another translation unit)?
>
> C++ will call it as it would any other C function.
>
>> What calling convention is used when that function calls some other
>> function (be it C, C++ or C++ with extern "C" declaration)? What if that
>> other function throws an exception?
>
> extern "C" has no effect here.

So if the function in question (the one in C++, with extern "C")
receives a function pointer, and calls it, it will be called in C++
convention (the current one for the compiler+architecture)?... :-O

How to make it call this anonymous function pointer in C convention?

Goran Pusic

unread,
Aug 25, 2010, 10:44:24 AM8/25/10
to
On Aug 25, 4:18 pm, Stanisław Findeisen <nore...@eisenbits.com> wrote:
> On 2010-08-25 10:50, Ian Collins wrote:
>
>
>
> > On 08/25/10 07:42 PM, Stanisław Findeisen wrote:
> >> On 2010-08-25 04:50, BGB / cr88192 wrote:
> >>> "Ian Collins"<ian-n...@hotmail.com>  wrote in message

Short answer: look up you compiler documentation. This is compiler-
dependent.

Long answer:

It doesn't look like you have read posts here. There is no such thing
as "C (or C++) calling convention".

There is "my compiler does X when I call a C function". It's __all__
compiler/compiler version/software/hardware platform dependent! And on
any given compiler, there are several options, even for C!

Any compiler provides you with a way to specify what calling
convention you want from a list of calling conventions chosen by that
compiler (look for e.g. __cdecl).

In reality, platform APIs specify these things, so compilers align.
And since both C and C++ code need to call system APIs, it's
effectively platform that decides (part of) this list.

Goran.

BGB / cr88192

unread,
Aug 25, 2010, 1:14:39 PM8/25/10
to

"James Kanze" <james...@gmail.com> wrote in message
news:dcd645ba-395a-4915...@z10g2000yqb.googlegroups.com...

this may depend some on the specific compiler, ...
for example, I have not seen this problem pop up with Cygwin or MinGW, but
it pops up fairly often with MSVC.

the reason I suspect is because they link in the runtime libraries
differently:
Cygwin and MinGW tend to use separate DLL's for the runtime (Cygwin using
'cygwin1.dll', and MinGW using 'msvcrt.dll' and others);
MSVC tends to default to hard-linking the runtime libraries, which can
result in crashing when passing file memory or file references (yes, I have
seen it happen, and the results are fairly consistent, more specifically, it
is malloc()'ed memory and stdio FILE's, ...).

granted, if no one in the other DLL ever tries to do IO on the file, or
release the memory, there is no problem.
usual strategy though is to have wrappers in the original DLL, where one
passes the references back to where they came from to operate on the file or
free memory.

also wrapping IO operations also makes it work, so long as the IO is done in
the original DLL...


note that this issue does not apply to memory of files opened via Win32 API
calls (GlobalAlloc, VirtualAlloc, ...), since these are handled differently.


but, yes, this is a fairly platform-specific issue...


BGB / cr88192

unread,
Aug 25, 2010, 1:34:59 PM8/25/10
to

"James Kanze" <james...@gmail.com> wrote in message
news:76ae0f08-dec7-448d...@x25g2000yqj.googlegroups.com...

> On Aug 25, 3:50 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
>> "Ian Collins" <ian-n...@hotmail.com> wrote in message
>
>> news:8dir1p...@mid.individual.net...
>
>> > On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
>> >> Given an architecture and a language (C or C++), is there any standard
>> >> function calling convention? Or is it compiler dependent?
>
>> > The two languages are different. With C, there will be a platform
>> > standard, with C++ it is still (regrettably) compiler specific.
>
>> yep...
>
>> however, typically, C++ uses the same basic calling convention as C, but
>> usually differing only in that the C++ case tends to use a name-mangling
>> scheme (often compiler specific, but some "de-facto" conventions exist,
>> for
>> example the use of MSVC-like conventions on Windows and the IA-64 ABI
>> name-mangling on Linux).
>
> How can it? Things like the layout of the vtable are part of
> the calling conventions, and C++ can't possibly use the same
> ones as C here.
>

simply:
C doesn't have vtables (or, at least, compiler generated ones);
in the C++ case, they are structures.

effectively, then, vtables are part of the ABI, but are not part of the
calling convention.


>> there does tend to be a difference in how compilers pass
>> 'this', with some compilers using an additional register
>> (thiscall in MSVC), but more commonly it is passed as a hidden
>> first argument (although AFAIK usually after the hidden first
>> argument used for returning structs).
>
> Except on Intel, the first argument *is* usually in a register.
>

not in cdecl or stdcall...
cdecl and stdcall tend to pass *everything* on the stack.

64-bit Windows and Linux pass arguments in registers.
fastcall also uses registers, but fastcall is rarely the default convention
(usually it has to be specified manually).

thiscall (typical on Windows) passes 'this' in ecx, but AFAIK this does not
extend to any other (non-this) arguments.


>> although, it is not really "safe" to rely on the specifics of
>> any of this...
>
>> similarly, it is not really "safe" to use C++-based APIs
>> across library boundaries, nor for that matter to pass memory
>> or file references between DLL's (this leads to "fun"
>> sometimes...).
>
> That's not true, and I've done it on many platforms.
>

something can easily "work" in many cases, but still not be "safe" in a
portability sense.
if one can do it, they can declare that it "works on most platforms of
interest", which may exclude some edge cases (for example, most PC or server
targetted code will not work on embedded systems, ...).


as for C++ ABI's, the main issue is that MSVC and MinGW on Windows use
different C++ ABI's, and so if one wants to support use of either compiler
(with pre-existing binary code), it is best to avoid using C++ as a basis
for API's.

other compilers tend to have other ABI's as well, and so this leaves the C
ABI as the "most portable" option.


using 'extern "C"' generally works without issue though, so long as one
fully adheres to C restrictions at the API level.


>> for example, MSVC likes giving each DLL its own local C library,
>
> MSVC does what you tell it in this regard. If you tell it to
> give each DLL its own local C library, when you don't want to,
> it's nobody's fault but your own.
>

this is the default behavior.
one has to tell it to do otherwise, but then it uses 'msvcr80.dll', which
has to be supplied manually on WinXP.


>> and hence, its own local memory heap and set of open files,
>> resulting in a few issues which may pop up occassionally...
>> (these issues don't tend to pop up with MinGW or Cygwin, as
>> these handle this situation differently...).
>
> I don't know about MinGW or Cygwin, but under most Unix, it's
> also possible to arrange things so that each shared object has
> its own free space arena as well, if this is what you want.
>

yes, but this is not necessarily a desirable feature, and is actually kind
of annoying sometime...

Marc

unread,
Aug 25, 2010, 1:48:02 PM8/25/10
to
On 25 août, 16:18, Stanisław Findeisen <nore...@eisenbits.com> wrote:
> So if the function in question (the one in C++, with extern "C")
> receives a function pointer, and calls it, it will be called in C++
> convention (the current one for the compiler+architecture)?... :-O
>
> How to make it call this anonymous function pointer in C convention?

"function" and "C-linkage function" are 2 different types in C++.
Indeed, you can even check that a function like qsort, which takes a
comparison function as argument, is overloaded so it can take either a
C++ function or a C function (well, you can't with g++, which wrongly
considers them as the same type).

Note that by default, a function pointer is a C++ function pointer,
except inside an extern "C" block where it is a C function pointer. If
you want to mix (use C function pointers in a C++ function for
instance), you need a typedef.

BGB / cr88192

unread,
Aug 25, 2010, 1:53:16 PM8/25/10
to

"Goran Pusic" <gor...@cse-semaphore.com> wrote in message
news:3c20014a-0f95-4941...@h19g2000yqb.googlegroups.com...

On Aug 24, 10:56 pm, Stanisław Findeisen <nore...@eisenbits.com>
wrote:
> Given an architecture and a language (C or C++), is there any standard
> function calling convention? Or is it compiler dependent?

<--


As far as I know, and as far as the language is concerned, calling
convention is absolutely 100% compiler and underlying CPU architecture
dependent^^^. (Is there some standard-dratft-dwelling-newsgroupie to
refute/confirm this?). If you look at e.g. C99 standard draft (and I
doubt it's different for previous versions), you will find no
mentioning of "calling convention", no "cdecl" or whatever, no
nothing.

-->

although this is also the sort of "standards'ism" that results in a person
not being able to do much of anything useful, portable or not...

in reality, the existence of calling conventions (such as cdecl, thiscall,
Win64, AMD64, ...), is inescapable, just as the matter of the existence of
specific CPU architectures is inescapable...

James Kanze

unread,
Aug 25, 2010, 2:28:25 PM8/25/10
to
On Aug 25, 6:14 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "James Kanze" <james.ka...@gmail.com> wrote in message

> news:dcd645ba-395a-4915...@z10g2000yqb.googlegroups.com...
> > On Aug 25, 4:12 am, Ian Collins <ian-n...@hotmail.com> wrote:
> >> On 08/25/10 02:50 PM, BGB / cr88192 wrote:

> > [...]
> >> > similarly, it is not really "safe" to use C++-based APIs
> >> > across library boundaries, nor for that matter to pass
> >> > memory or file references between DLL's (this leads to "fun"
> >> > sometimes...).

> >> That is very platform specific. Those restrictions don't
> >> apply to Unix or Unix like systems.

> > Which part of his statement are you referring to? It's not safe
> > to use C++ based APIs (with std::string, etc.) between code
> > compiled with different compiler options, with the same
> > compiler. And there's no problem passing memory or file
> > references between dynamically loaded object files on any of the
> > systems I've worked on, Windows or Unix. (We do it all the time
> > under Windows, here, and we did it regularly under Solaris and
> > Linux where I was before.)

> this may depend some on the specific compiler, ...
> for example, I have not seen this problem pop up with Cygwin
> or MinGW, but it pops up fairly often with MSVC.

I've not seen it with any compiler.

> the reason I suspect is because they link in the runtime libraries
> differently:
> Cygwin and MinGW tend to use separate DLL's for the runtime (Cygwin using
> 'cygwin1.dll', and MinGW using 'msvcrt.dll' and others);
> MSVC tends to default to hard-linking the runtime libraries,

As far as I can tell, VC++ doesn't default to anything. You
always have to specify: /MD or /MDd.

--
James Kanze

James Kanze

unread,
Aug 25, 2010, 2:33:05 PM8/25/10
to
On Aug 25, 3:44 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:

> On Aug 25, 4:18 pm, Stanis³aw Findeisen <nore...@eisenbits.com> wrote:

[...]


> Any compiler provides you with a way to specify what calling
> convention you want from a list of calling conventions chosen by that
> compiler (look for e.g. __cdecl).

On most machines, there is only one reasonable way to pass
arguments when calling a function, and most compilers do not
need or have extensions to specify many different calling
conventions---they use the standard ``extern "language"''.

--
James Kanze

James Kanze

unread,
Aug 25, 2010, 2:44:09 PM8/25/10
to
On Aug 25, 6:34 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "James Kanze" <james.ka...@gmail.com> wrote in message

> news:76ae0f08-dec7-448d...@x25g2000yqj.googlegroups.com...
> > On Aug 25, 3:50 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> >> "Ian Collins" <ian-n...@hotmail.com> wrote in message

> >>news:8dir1p...@mid.individual.net...

> >> > On 08/25/10 08:56 AM, Stanislaw Findeisen wrote:
> >> >> Given an architecture and a language (C or C++), is there any standard
> >> >> function calling convention? Or is it compiler dependent?

> >> > The two languages are different. With C, there will be a platform
> >> > standard, with C++ it is still (regrettably) compiler specific.

> >> yep...

> >> however, typically, C++ uses the same basic calling
> >> convention as C, but usually differing only in that the C++
> >> case tends to use a name-mangling scheme (often compiler
> >> specific, but some "de-facto" conventions exist, for
> >> example the use of MSVC-like conventions on Windows and the
> >> IA-64 ABI name-mangling on Linux).

> > How can it? Things like the layout of the vtable are part
> > of the calling conventions, and C++ can't possibly use the
> > same ones as C here.

> simply:
> C doesn't have vtables (or, at least, compiler generated ones);
> in the C++ case, they are structures.

> effectively, then, vtables are part of the ABI, but are not part of the
> calling convention.

The calling convention and the ABI are basically two words for
the same thing.

> >> there does tend to be a difference in how compilers pass
> >> 'this', with some compilers using an additional register
> >> (thiscall in MSVC), but more commonly it is passed as a hidden
> >> first argument (although AFAIK usually after the hidden first
> >> argument used for returning structs).

> > Except on Intel, the first argument *is* usually in a register.

(On rereading it, I find my phrase a bit ambiguous. The "Except
on Intel" should apply to what I've written. On architectures
other than Intel, the first argument (or the first n
arguments---5 on a Sparc) are passed in registers.

> not in cdecl or stdcall...
> cdecl and stdcall tend to pass *everything* on the stack.

What is cdecl or stdcall? They don't exist on most compilers
I've used. And as I said, except on Intel, the first
n arguments are normally passed in registers.

> >> although, it is not really "safe" to rely on the specifics of
> >> any of this...

> >> similarly, it is not really "safe" to use C++-based APIs
> >> across library boundaries, nor for that matter to pass memory
> >> or file references between DLL's (this leads to "fun"
> >> sometimes...).

> > That's not true, and I've done it on many platforms.

> something can easily "work" in many cases, but still not be
> "safe" in a portability sense.

For what definition of "safe"? You define the constraints of
your library (usually, by specifying what options must be used
when compiling code which links to it). If the user conforms to
those constraints, there's no problem.

> if one can do it, they can declare that it "works on most
> platforms of interest", which may exclude some edge cases (for
> example, most PC or server targetted code will not work on
> embedded systems, ...).

Well, obviously, you can't write a portable dll which will work
on a system which doesn't have dlls.

> as for C++ ABI's, the main issue is that MSVC and MinGW on
> Windows use different C++ ABI's, and so if one wants to
> support use of either compiler (with pre-existing binary
> code), it is best to avoid using C++ as a basis for API's.

VC++ and g++ both change the C++ ABI depending on compiler
options. So what else is new? Your client code must be
compiled with the same compiler (or one which guarantees binary
compatibility), using the same options.

> other compilers tend to have other ABI's as well, and so this
> leaves the C ABI as the "most portable" option.

I think we're talking at cross purposes. For binary
compatibility, yes, C is the only real solution. I was talking
about source code compatilibity.

> using 'extern "C"' generally works without issue though, so
> long as one fully adheres to C restrictions at the API level.

> >> for example, MSVC likes giving each DLL its own local C library,

> > MSVC does what you tell it in this regard. If you tell it to
> > give each DLL its own local C library, when you don't want to,
> > it's nobody's fault but your own.

> this is the default behavior. one has to tell it to do
> otherwise, but then it uses 'msvcr80.dll', which has to be
> supplied manually on WinXP.

I'm not aware of any "default" behavior. When I type in "cl
/help", it tells me to chose one of /MT, /MTd, /MD or /MDd
(indirectly, at least). And every Windows application I've
worked on uses /MD or /MDd, which doesn't cause any problems.

> >> and hence, its own local memory heap and set of open files,
> >> resulting in a few issues which may pop up occassionally...
> >> (these issues don't tend to pop up with MinGW or Cygwin, as
> >> these handle this situation differently...).

> > I don't know about MinGW or Cygwin, but under most Unix, it's
> > also possible to arrange things so that each shared object has
> > its own free space arena as well, if this is what you want.

> yes, but this is not necessarily a desirable feature, and is
> actually kind of annoying sometime...

It depends on what you're doing. If you're supporting third
party plugins, you'd like them to be as isolated as possible.

--
James Kanze

Ian Collins

unread,
Aug 25, 2010, 5:57:13 PM8/25/10
to
On 08/26/10 12:55 AM, James Kanze wrote:
> On Aug 25, 4:12 am, Ian Collins<ian-n...@hotmail.com> wrote:
>> On 08/25/10 02:50 PM, BGB / cr88192 wrote:
>
> [...]
>>> similarly, it is not really "safe" to use C++-based APIs
>>> across library boundaries, nor for that matter to pass
>>> memory or file references between DLL's (this leads to "fun"
>>> sometimes...).
>
>> That is very platform specific. Those restrictions don't
>> apply to Unix or Unix like systems.
>
> Which part of his statement are you referring to?

Most of it.

> It's not safe
> to use C++ based APIs (with std::string, etc.) between code
> compiled with different compiler options, with the same
> compiler.

He wasn't specific, as you are. Build everything with the same compiler
and options and there aren't any problems using C++ based APIs.

> And there's no problem passing memory or file
> references between dynamically loaded object files on any of the
> systems I've worked on, Windows or Unix. (We do it all the time
> under Windows, here, and we did it regularly under Solaris and
> Linux where I was before.)

Quite. I've never heard of that restriction.

--
Ian Collins

Joshua Maurice

unread,
Aug 25, 2010, 6:02:27 PM8/25/10
to

I think this is partially from older windows compilers which had the
option to compile the C standard library statically into a dll. When
this was done, each statically linked c standard library had its own
heap (and other resource managers), so you could not "new" some memory
in one dll and "delete" it in another. This problem is neatly solved
nowadays by dynamically linking to the C standard library. Didn't some
of the newer versions of Microsoft's visual studios devenv.exe remove
C std lib static linking as an option entirely? I guess Microsoft is
playing slowpoke catchup with good practice as always.

Ian Collins

unread,
Aug 25, 2010, 6:03:32 PM8/25/10
to
On 08/26/10 05:34 AM, BGB / cr88192 wrote:

> "James Kanze"<james...@gmail.com> wrote:
>> On Aug 25, 3:50 am, "BGB / cr88192"<cr88...@hotmail.com> wrote:
>
>>> there does tend to be a difference in how compilers pass
>>> 'this', with some compilers using an additional register
>>> (thiscall in MSVC), but more commonly it is passed as a hidden
>>> first argument (although AFAIK usually after the hidden first
>>> argument used for returning structs).
>>
>> Except on Intel, the first argument *is* usually in a register.
>>
> not in cdecl or stdcall...
> cdecl and stdcall tend to pass *everything* on the stack.

Eh?

> 64-bit Windows and Linux pass arguments in registers.

That is because that's what the AMD64 ABI specifies.

> fastcall also uses registers, but fastcall is rarely the default convention
> (usually it has to be specified manually).

fastcall?

--
Ian Collins

BGB / cr88192

unread,
Aug 25, 2010, 7:05:48 PM8/25/10
to

"Joshua Maurice" <joshua...@gmail.com> wrote in message
news:07722e12-2a4b-4faf...@x24g2000pro.googlegroups.com...

On Aug 25, 2:57 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 08/26/10 12:55 AM, James Kanze wrote:
> > And there's no problem passing memory or file
> > references between dynamically loaded object files on any of the
> > systems I've worked on, Windows or Unix. (We do it all the time
> > under Windows, here, and we did it regularly under Solaris and
> > Linux where I was before.)
>
> Quite. I've never heard of that restriction.

<--


I think this is partially from older windows compilers which had the
option to compile the C standard library statically into a dll. When
this was done, each statically linked c standard library had its own
heap (and other resource managers), so you could not "new" some memory
in one dll and "delete" it in another. This problem is neatly solved
nowadays by dynamically linking to the C standard library. Didn't some
of the newer versions of Microsoft's visual studios devenv.exe remove
C std lib static linking as an option entirely? I guess Microsoft is
playing slowpoke catchup with good practice as always.

-->

apparently, AFAICT, they had reverted to statically-linking the thing, or at
least this is my experience.
why? I don't know...

note that I am using the Platform SDK v6.1 on WinXP, so this is not exactly
an old version of MSVC.

for some things, have also been using Visual Studio 2008, which uses v6.0A.

BGB / cr88192

unread,
Aug 25, 2010, 7:25:27 PM8/25/10
to

"James Kanze" <james...@gmail.com> wrote in message
news:13533014-dba5-456f...@l6g2000yqb.googlegroups.com...

On Aug 25, 3:44 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:
> On Aug 25, 4:18 pm, Stanisław Findeisen <nore...@eisenbits.com> wrote:

[...]
> Any compiler provides you with a way to specify what calling
> convention you want from a list of calling conventions chosen by that
> compiler (look for e.g. __cdecl).

<--


On most machines, there is only one reasonable way to pass
arguments when calling a function, and most compilers do not
need or have extensions to specify many different calling
conventions---they use the standard ``extern "language"''.
-->

well, if one excludes 32 bit Windows, where in practice 4 calling
conventions are commonly used:
cdecl; stdcall; fastcall; and thiscall (modified cdecl).

in most cases, fastcall can be ignored (it is almost never used for external
linkage AFAICT), and thiscall can simply be regarded as a special case of
cdecl.


this is a major reason for modifier tags like WINAPI and similar: they wrap
the calling convention keywords.


on 64-bit Windows, there is a single calling convention (Win64);
on 64-bit Linux and OSX, there is a single calling convention (AMD64);

on 32-bit Linux, in practice pretty much everyone just uses cdecl...


IIRC, MS-DOS was a mess though, with many compilers doing things
differently, so code from one compiler would not normally link correctly
with code produced by another. 32-bit Windows mostly stabilized the calling
convention and object-file format mess (nearly everything is either cdecl or
stdcall, and uses COFF...).

BGB / cr88192

unread,
Aug 25, 2010, 7:44:58 PM8/25/10
to

"Ian Collins" <ian-...@hotmail.com> wrote in message
news:8dli9k...@mid.individual.net...

> On 08/26/10 05:34 AM, BGB / cr88192 wrote:
>> "James Kanze"<james...@gmail.com> wrote:
>>> On Aug 25, 3:50 am, "BGB / cr88192"<cr88...@hotmail.com> wrote:
>>
>>>> there does tend to be a difference in how compilers pass
>>>> 'this', with some compilers using an additional register
>>>> (thiscall in MSVC), but more commonly it is passed as a hidden
>>>> first argument (although AFAIK usually after the hidden first
>>>> argument used for returning structs).
>>>
>>> Except on Intel, the first argument *is* usually in a register.
>>>
>> not in cdecl or stdcall...
>> cdecl and stdcall tend to pass *everything* on the stack.
>
> Eh?
>

yep.

usually, cdecl functions go like:
push ebp
mov ebp, esp
sub esp, <something>
...
mov esp, ebp ;or sometimes "add esp, <something>"
pop ebp
ret

within the function, (except when returning structs):
[ebp+8] ;arg0
[ebp+12] ;arg1
[ebp+16] ;arg2
[ebp+20] ;arg3
...

stdcall functions are similar, except they tend to use "ret <argsize>" vs
"ret", which also removes arguments from the stack.

cdecl has another name, like "SysV i386 ABI" or similar.
stdcall was apparently created by MS, and I don't know of another name for
it.


struct returning tended to be not entirely consistent between compilers, but
just assuming the "generic" way of returning structs (passing an extra
hidden argument to tell the called function where to put the struct) seems
to work for the most part.


>> 64-bit Windows and Linux pass arguments in registers.
>
> That is because that's what the AMD64 ABI specifies.
>

yep.


>> fastcall also uses registers, but fastcall is rarely the default
>> convention
>> (usually it has to be specified manually).
>
> fastcall?
>

it was another convention used by MS and others, where the idea was that the
first some-odd arguments would be passed in registers rather than on the
stack, but it was not well standardized.

http://en.wikipedia.org/wiki/Fastcall

MS's variant (the most common one AFAIK) used ECX and EDX for argument
passing.

Goran Pusic

unread,
Aug 26, 2010, 3:03:59 AM8/26/10
to
> it was another convention used by MS and others, where the idea was that the
> first some-odd arguments would be passed in registers rather than on the
> stack, but it was not well standardized.
>
> http://en.wikipedia.org/wiki/Fastcall
>
> MS's variant (the most common one AFAIK) used ECX and EDX for argument
> passing.

Heh, a blast from the past! Yes, Borland's fastcall was different from
MS's fastcall.

There's no "standardization" here, jut convention.

Goran.

James Kanze

unread,
Aug 26, 2010, 6:20:55 AM8/26/10
to
On Aug 26, 12:25 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "James Kanze" <james.ka...@gmail.com> wrote in message

> news:13533014-dba5-456f...@l6g2000yqb.googlegroups.com...
> On Aug 25, 3:44 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:

> > On Aug 25, 4:18 pm, Stanis³aw Findeisen <nore...@eisenbits.com> wrote:

> [...]

> > Any compiler provides you with a way to specify what calling
> > convention you want from a list of calling conventions chosen by that
> > compiler (look for e.g. __cdecl).

> <--
> On most machines, there is only one reasonable way to pass
> arguments when calling a function, and most compilers do not
> need or have extensions to specify many different calling
> conventions---they use the standard ``extern "language"''.
> -->

> well, if one excludes 32 bit Windows, where in practice 4 calling
> conventions are commonly used:
> cdecl; stdcall; fastcall; and thiscall (modified cdecl).

By "most machines", I meant most types of machines. Windows is
a bit of an exception, although even here, it's only really an
exception when using VC++, who decided not to use the standard
mechanism. (cdecl and stdcall resolve to ``extern "C"'' and
``extern "Pascal"'', I think. And thiscall is an extension of
cdecl, only relevant for ``extern "C++"''. The language also
allows a compiler to define something like ``extern "Fast"'',
although why one would use a slow call when a fast one is
available is beyond me.)

> in most cases, fastcall can be ignored (it is almost never
> used for external linkage AFAICT), and thiscall can simply be
> regarded as a special case of cdecl.

> this is a major reason for modifier tags like WINAPI and
> similar: they wrap the calling convention keywords.

> on 64-bit Windows, there is a single calling convention (Win64);
> on 64-bit Linux and OSX, there is a single calling convention (AMD64);

As is the case under Solaris, HP/UX and AIX. And probably every
other system around.

> on 32-bit Linux, in practice pretty much everyone just uses
> cdecl...

On 32-bit Linux, I've never used anything.

> IIRC, MS-DOS was a mess though, with many compilers doing
> things differently, so code from one compiler would not
> normally link correctly with code produced by another.

Yes and no. All of the C compilers I tried did the same thing.
All of the C++ compilers were different. But that's the case
almost universally today as well.

> 32-bit Windows mostly stabilized the calling convention and
> object-file format mess (nearly everything is either cdecl or
> stdcall, and uses COFF...).

Windows defines an ABI for C, I think (which it uses when
calling into system DLL's).

--
James Kanze

Goran Pusic

unread,
Aug 26, 2010, 9:00:11 AM8/26/10
to
On Aug 26, 12:20 pm, James Kanze <james.ka...@gmail.com> wrote:
> Windows defines an ABI for C, I think (which it uses when
> calling into system DLL's).

Hey! That should be "Windows defines an ABI, full stop". :-)

Why "for C" part? Many self-respecting toolchains on windows,
including some completely oblivious to C in particular, implement
whatever is necessary to be able to call into system without going
over anything C. Old VB6- does that, FreePascal/Delphi do it, of
course .NET does it...

In fact, I'd go as far as to say that any given system effectively has
a language-agnostic ABI (but they all lean towards simplicity of C).

Goran.

Bo Persson

unread,
Aug 26, 2010, 12:07:24 PM8/26/10
to

The fact that MS used their C compiler when creating the API might
have had an influence. :-)


Bo Persson


James Kanze

unread,
Aug 26, 2010, 12:34:09 PM8/26/10
to
On Aug 26, 2:00 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:
> On Aug 26, 12:20 pm, James Kanze <james.ka...@gmail.com> wrote:

> > Windows defines an ABI for C, I think (which it uses when
> > calling into system DLL's).

> Hey! That should be "Windows defines an ABI, full stop". :-)

> Why "for C" part?

Because the ABI is defined in C.

> Many self-respecting toolchains on windows, including some
> completely oblivious to C in particular, implement whatever is
> necessary to be able to call into system without going over
> anything C.

Because both the Windows and the Unix system interfaces are
defined in C, most languages support calling into C. Most
languages also have their own libraries, which mask the C part.
You can write code in just about any language without ever using
the Windows ABI.

> Old VB6- does that, FreePascal/Delphi do it, of
> course .NET does it...

> In fact, I'd go as far as to say that any given system
> effectively has a language-agnostic ABI (but they all lean
> towards simplicity of C).

That used to be true in the distant past, but not today.

--
James Kanze

BGB / cr88192

unread,
Aug 26, 2010, 1:55:24 PM8/26/10
to

"James Kanze" <james...@gmail.com> wrote in message
news:ef1763bb-d598-49f6...@k10g2000yqa.googlegroups.com...

On Aug 26, 12:25 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "James Kanze" <james.ka...@gmail.com> wrote in message

> news:13533014-dba5-456f...@l6g2000yqb.googlegroups.com...
> On Aug 25, 3:44 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:

> > On Aug 25, 4:18 pm, Stanisław Findeisen <nore...@eisenbits.com> wrote:

> [...]

> > Any compiler provides you with a way to specify what calling
> > convention you want from a list of calling conventions chosen by that
> > compiler (look for e.g. __cdecl).

> <--
> On most machines, there is only one reasonable way to pass
> arguments when calling a function, and most compilers do not
> need or have extensions to specify many different calling
> conventions---they use the standard ``extern "language"''.
> -->

> well, if one excludes 32 bit Windows, where in practice 4 calling
> conventions are commonly used:
> cdecl; stdcall; fastcall; and thiscall (modified cdecl).

<--


By "most machines", I meant most types of machines. Windows is
a bit of an exception, although even here, it's only really an
exception when using VC++, who decided not to use the standard
mechanism. (cdecl and stdcall resolve to ``extern "C"'' and
``extern "Pascal"'', I think. And thiscall is an extension of
cdecl, only relevant for ``extern "C++"''. The language also
allows a compiler to define something like ``extern "Fast"'',
although why one would use a slow call when a fast one is
available is beyond me.)

-->

yeah.

most compilers I have seen have used the "__callconv" type keywords,
although granted my experience is mostly limited to Windows (where this
convention would likely be default as MS uses it), and Linux (where
generally there is only a single calling convention in use, hence no real
need to use it...).

this notation makes a little more sense IMO than the 'extern "lang" '
notation in many cases, as it allows defining the calling convention of
function pointers, ... which the former can't do effectively, however, the
'extern "lang" ' notation does have the usefulness that it can be applied to
an entire block of definitions, rather than having to be endlessly repeated
for each declaration.

hence:
void (__stdcall *foo)(int x, double y);

and:
extern "C"
{
...
}


> in most cases, fastcall can be ignored (it is almost never
> used for external linkage AFAICT), and thiscall can simply be
> regarded as a special case of cdecl.

> this is a major reason for modifier tags like WINAPI and
> similar: they wrap the calling convention keywords.

> on 64-bit Windows, there is a single calling convention (Win64);
> on 64-bit Linux and OSX, there is a single calling convention (AMD64);

<--


As is the case under Solaris, HP/UX and AIX. And probably every
other system around.

-->

most non-Windows systems on x86-64 AFAIK use AMD64.

admittedly, I personally like Win64's design a little more, as AMD64 seems a
bit complicated and over-engineered and likely to actually reduce
performance slightly in common use cases vs Win64's design.


> on 32-bit Linux, in practice pretty much everyone just uses
> cdecl...

<--


On 32-bit Linux, I've never used anything.

-->

on 32-bit Linux, there is only a single calling convention in single use, so
no one needs to...
doesn't mean the calling convention is not there, only that it is not needed
to specify it.


> IIRC, MS-DOS was a mess though, with many compilers doing
> things differently, so code from one compiler would not
> normally link correctly with code produced by another.

<--


Yes and no. All of the C compilers I tried did the same thing.
All of the C++ compilers were different. But that's the case
almost universally today as well.

-->

there were differences.
many C compilers used OMF (as the object format), and some used others
(including COFF, but this was typically for DPMI-based compilers, as well as
I think I remember there being 32-bit OMF, ...);
there were a few others as well IIRC.

although, all this was long ago, and my memory is faded.


> 32-bit Windows mostly stabilized the calling convention and
> object-file format mess (nearly everything is either cdecl or
> stdcall, and uses COFF...).

<--


Windows defines an ABI for C, I think (which it uses when
calling into system DLL's).
-->

well, or it can be said that there are 2 in common use:
stdcall (used for many DLL's) and cdecl (used for pretty much everything
else).

supporting both, one can interface with pretty much anything of relevance.

on many other systems, it is a single convention in use, but which it is
will vary from system to system (and the specifics will depend on the CPU
arch, ...).

but, Windows and x86 (or Windows and x64 / x86-64) represent the vast
majority of total systems (desktop and laptop at least) in use...
Linux and OSX (on x86 or x86-64) are most of the rest.

ARM and PPC are used in many embedded systems.
(not sure the OS popularity distribution for embedded systems, from what I
have seen I would guess: Linux, FreeDOS, and various proprietary OS's...).

most other architectures and operating systems can be largely safely
ignored...

in my case, I am still using the C calling conventions (for the specific
targets I support, mostly Windows and Linux), even for non-C languages (my
partial Java and C# implementation, as well as BGBScript, which is based on
ECMAScript).

granted, I do tend to use a modified ABI (I see the calling convention and
ABI as separate-but related, where an ABI may specify things not part of the
calling convention proper, and the calling convention is mostly responsible
for how data gets to/from the function on a given arch, but ignores
secondary issues such as function naming or sideband data).

yes, closures and similar are a bit of a hack (they use heap-allocated
"executable objects"), and there is no "good" way to handle full
continuations, so I largely ignore the latter (partial continuations can be
handled via a longjmp-like mechanism).

C level interop is possible then, but direct C++ level interop is not.
plugging between C++ and BGBScript would still require using 'extern "C" ',
and does not directly facilitate high-level types.
however, some level of interop is facilitated by dynamic code-generation
(mostly to try to patch together the BGBScript and C typesystems, where one
supports dynamic typing, and the other is primarily statically-typed...).

note: apart from some amount of either link-time or run-time generated code,
my ABI wouldn't work...
the ABI was largely originally designed to deal with dynamically-generated
code (though some information is redundant, as I originally designed it
before moving to using a database-like structure for code patching, so the
ABI had to be largely self-defining, rather than being able to rely on
external metadata queries to resolve many issues).

I had considered some possibility of using other (more specialized) calling
conventions, but decided against this due to the overall costs (for example,
a calling convention capable of pulling off full continuations would
necessarily have problems with C-level interop, and I know of know good way
to support full continuations in C apart from ugly stack-jumping hackery,
which is preferably avoided...).

static linking of C or C++ against BGBScript (or later C# or Java) also
currently doesn't work, as there is no real "good" way to handle late
binding in statically-compiled code (this means it is needed to fetch and
call through function pointers...).

dynamically-compiled C doesn't have this issue though (but has its own share
of issues, mostly the plague of compiler bugs...).


and so on...


Paavo Helde

unread,
Aug 26, 2010, 3:01:43 PM8/26/10
to
Joshua Maurice <joshua...@gmail.com> wrote in news:07722e12-2a4b-
4faf-acb9-2...@x24g2000pro.googlegroups.com:

> This problem is neatly solved
> nowadays by dynamically linking to the C standard library. Didn't some
> of the newer versions of Microsoft's visual studios devenv.exe remove
> C std lib static linking as an option entirely? I guess Microsoft is
> playing slowpoke catchup with good practice as always.

The dynamic runtime means that you have to distribute and install it
separately. If the aim is to provide a very simple single-exe utility
requiring no install, then static linking simplifies the things a lot.

Even with DLL-s the static linking to RTL can be used, but instead of
malloc and friends one has to provide wrapped versions like my_malloc and
my_cpp_allocator, defined in one DLL only. These must then be used for
allocating things which are passed over DLL boundaries.

Cheers
Paavo


Goran Pusic

unread,
Aug 27, 2010, 2:30:42 AM8/27/10
to
On Aug 26, 6:34 pm, James Kanze <james.ka...@gmail.com> wrote:
> > In fact, I'd go as far as to say that any given system
> > effectively has a language-agnostic ABI (but they all lean
> > towards simplicity of C).
>
> That used to be true in the distant past, but not today.

I am sorry, but no. Additional argument to the way I see things: under
e.g. Windows, there's a myriad of OS interfaces that are exposed
through COM (e.g. Telephony API, to name but one example). Nobody in
their right mind is using these interfaces from C, but rather C++.

IOW, in theory, C language is incidental to OS interfaces. In
practice, much less so. :-)

Goran.

BGB / cr88192

unread,
Aug 27, 2010, 2:54:44 PM8/27/10
to

"Goran Pusic" <gor...@cse-semaphore.com> wrote in message
news:ecc5988b-8704-4e33...@z28g2000yqh.googlegroups.com...

On Aug 26, 6:34 pm, James Kanze <james.ka...@gmail.com> wrote:
> > In fact, I'd go as far as to say that any given system
> > effectively has a language-agnostic ABI (but they all lean
> > towards simplicity of C).
>
> That used to be true in the distant past, but not today.

<--


I am sorry, but no. Additional argument to the way I see things: under
e.g. Windows, there's a myriad of OS interfaces that are exposed
through COM (e.g. Telephony API, to name but one example). Nobody in
their right mind is using these interfaces from C, but rather C++.

IOW, in theory, C language is incidental to OS interfaces. In
practice, much less so. :-)

-->

is there any "particular" reason why people should not use COM interfaces
from C?...

one can argue, maybe it doesn't "mesh" with C's "normal way of doing things"
/ aesthetics, but this does not itself limit its usability (hell, maybe it
can just be claimed that using COM interfaces makes C look a little more
like C++?...).

and, if people *really* don't like the aesthetics, they can always just wrap
the thing.


in fact, there are several (mostly/purely) C codebases I know of that
internally use systems fairly similar to COM anyways, since it works well
for loosely coupled components (direct linking tends to cause problems in
certain cases, such as having a component which may or may not exist, ...,
so a COM-like system may be an improvement over some other strategies).

so then, what is the *real* basis for this claim?...

this sounds like personal bias, rather than an objective statement, FWIW...


or such...

Alf P. Steinbach /Usenet

unread,
Aug 27, 2010, 3:27:13 PM8/27/10
to
* BGB / cr88192, on 27.08.2010 20:54:

> "Goran Pusic"<gor...@cse-semaphore.com> wrote in message
> news:ecc5988b-8704-4e33...@z28g2000yqh.googlegroups.com...
> On Aug 26, 6:34 pm, James Kanze<james.ka...@gmail.com> wrote:
>>> In fact, I'd go as far as to say that any given system
>>> effectively has a language-agnostic ABI (but they all lean
>>> towards simplicity of C).
>>
>> That used to be true in the distant past, but not today.
>
> <--
> I am sorry, but no. Additional argument to the way I see things: under
> e.g. Windows, there's a myriad of OS interfaces that are exposed
> through COM (e.g. Telephony API, to name but one example). Nobody in
> their right mind is using these interfaces from C, but rather C++.
>
> IOW, in theory, C language is incidental to OS interfaces. In
> practice, much less so. :-)
> -->
>
> is there any "particular" reason why people should not use COM interfaces
> from C?...

No, but then "should" makes the question pretty meaningless, and "particular"
put in quotes completes the removal of meaning from the question.

It's like asking if there's any "particular" reason why people shouldn't use
assembly language.

COM was designed for C++ and is hard enough in C++. In C it's a nightmare. You
have to emulate all that the C++ compiler does for you, e.g transforming call
p->foo( x ) into p->vtable->foo( p, x ), perhaps with a cast, and so on.


> one can argue, maybe it doesn't "mesh" with C's "normal way of doing things"
> / aesthetics, but this does not itself limit its usability (hell, maybe it
> can just be claimed that using COM interfaces makes C look a little more
> like C++?...).

No, it just makes it look like gibberish.


> and, if people *really* don't like the aesthetics, they can always just wrap
> the thing.
>
>
> in fact, there are several (mostly/purely) C codebases I know of that
> internally use systems fairly similar to COM anyways, since it works well
> for loosely coupled components (direct linking tends to cause problems in
> certain cases, such as having a component which may or may not exist, ...,
> so a COM-like system may be an improvement over some other strategies).

Yes, that is correct. Mozilla uses a COM-based scheme, and so does a common GUI
in Linux.


> so then, what is the *real* basis for this claim?...
>
> this sounds like personal bias, rather than an objective statement, FWIW...

No, but it's not a complete picture. Some parts of the Windows API are designed
for C++, true. Those parts are most naturally used from C++ or higher level
languages. But most of it is designed for C, and those parts are at least usable
from C (although also that's easier in C++). And some parts are designed for
scripting languages, and those parts are easy to use with scripting, pretty
horrible to use from C++ without special supportive libraries, and don't even
think about C. Although some folks at Microsoft did, and wrote books about it.

The binary interface, the ABI, is in all cases language agnostic.

But since the APIs are designed for different languages, different languages are
what you use. The common ABI just makes it a tad easier to combine languages.
Like writing a DLL in language A and use it from language B. This ABI is however
not an ABI supporting modern C++. There's no provision for multiple inheritance
or RTTI or C++ constructors/destructors; from a C++ point of view it's like
interfacing with code written in another language.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>

Öö Tiib

unread,
Aug 27, 2010, 4:11:09 PM8/27/10
to
On 26 aug, 13:20, James Kanze <james.ka...@gmail.com> wrote:
>
> Windows defines an ABI for C, I think (which it uses when
> calling into system DLL's).
>

That ABI uses sort of Pascal way to call functions if i remember
correctly. Haven't looked long time into some ms header but i think
these are still that "stdcall".

BGB / cr88192

unread,
Aug 28, 2010, 2:09:05 AM8/28/10
to

"Alf P. Steinbach /Usenet" <alf.p.stein...@gmail.com> wrote in
message news:i593j0$gkq$1...@news.eternal-september.org...

>* BGB / cr88192, on 27.08.2010 20:54:
>> "Goran Pusic"<gor...@cse-semaphore.com> wrote in message
>> news:ecc5988b-8704-4e33...@z28g2000yqh.googlegroups.com...
>> On Aug 26, 6:34 pm, James Kanze<james.ka...@gmail.com> wrote:
>>>> In fact, I'd go as far as to say that any given system
>>>> effectively has a language-agnostic ABI (but they all lean
>>>> towards simplicity of C).
>>>
>>> That used to be true in the distant past, but not today.
>>
>> <--
>> I am sorry, but no. Additional argument to the way I see things: under
>> e.g. Windows, there's a myriad of OS interfaces that are exposed
>> through COM (e.g. Telephony API, to name but one example). Nobody in
>> their right mind is using these interfaces from C, but rather C++.
>>
>> IOW, in theory, C language is incidental to OS interfaces. In
>> practice, much less so. :-)
>> -->
>>
>> is there any "particular" reason why people should not use COM interfaces
>> from C?...
>
> No, but then "should" makes the question pretty meaningless, and
> "particular" put in quotes completes the removal of meaning from the
> question.
>
> It's like asking if there's any "particular" reason why people shouldn't
> use assembly language.


ASM works as well, just due to verbosity and lacking portability, usually
makes it a worse choice except in cases when there is some reason an actual
HLL can't reasonably be used.

but, yes, I still use a fair amount of ASM as well... (most often, for
dynamically generating code in memory, where my assembler tends to be much
faster and more reliable than my C compiler, sadly enough making ASM a much
more attractive language for this task).


> COM was designed for C++ and is hard enough in C++. In C it's a nightmare.
> You have to emulate all that the C++ compiler does for you, e.g
> transforming call p->foo( x ) into p->vtable->foo( p, x ), perhaps with a
> cast, and so on.
>

I have often seen it as:
(*p)->foo(p, x);

but, either way...


>
>> one can argue, maybe it doesn't "mesh" with C's "normal way of doing
>> things"
>> / aesthetics, but this does not itself limit its usability (hell, maybe
>> it
>> can just be claimed that using COM interfaces makes C look a little more
>> like C++?...).
>
> No, it just makes it look like gibberish.
>

I have seen plenty worse...

but, in many cases, a lot of ones' code can end up half-way looking like
this anyways, especially when doing OOP-like stuff, ...

context and vtable structs are not exactly a rare thing, and function
pointers are nothing to be afraid of, ...

either way, one still ends up with a lot of "foo->bar".


>
>> and, if people *really* don't like the aesthetics, they can always just
>> wrap
>> the thing.
>>
>>
>> in fact, there are several (mostly/purely) C codebases I know of that
>> internally use systems fairly similar to COM anyways, since it works well
>> for loosely coupled components (direct linking tends to cause problems in
>> certain cases, such as having a component which may or may not exist,
>> ...,
>> so a COM-like system may be an improvement over some other strategies).
>
> Yes, that is correct. Mozilla uses a COM-based scheme, and so does a
> common GUI in Linux.
>

yep.


>
>> so then, what is the *real* basis for this claim?...
>>
>> this sounds like personal bias, rather than an objective statement,
>> FWIW...
>
> No, but it's not a complete picture. Some parts of the Windows API are
> designed for C++, true. Those parts are most naturally used from C++ or
> higher level languages. But most of it is designed for C, and those parts
> are at least usable from C (although also that's easier in C++). And some
> parts are designed for scripting languages, and those parts are easy to
> use with scripting, pretty horrible to use from C++ without special
> supportive libraries, and don't even think about C. Although some folks at
> Microsoft did, and wrote books about it.
>
> The binary interface, the ABI, is in all cases language agnostic.
>

yes, fair enough.

in my case, I tend to also design my API's to be C friendly as well,
generally regarding C as "the least common denominator", and also it is the
implementation language of most of my other stuff as well.

also, many parts of my codebase are C-only, whereas others allow C++, as a
matter of policy.
technically, my policy also allows C# in some cases as well, but thus far I
don't use any C# in my main projects (thus far, it is an unreasonable
portability risk).


> But since the APIs are designed for different languages, different
> languages are what you use. The common ABI just makes it a tad easier to
> combine languages. Like writing a DLL in language A and use it from
> language B. This ABI is however not an ABI supporting modern C++. There's
> no provision for multiple inheritance or RTTI or C++
> constructors/destructors; from a C++ point of view it's like interfacing
> with code written in another language.
>

fair enough.

some of my own API's implement dynamic typing and GC, although in some parts
of my codebase its use is a bit spotty (since I also like modularity, and
parts which directly depend on the GC or typesystem library, naturally
enough have a dependency on said libraries).

in some cases, I have gone and used (COM-like) interfaces, as these can
allow accessing a facility, but can more gracefully deal with the case where
it is absent.


this tends to involve though using OS facilities to get some of the core
components loaded, so that one can fetch some of the core interfaces, and
then use these to load additional components and gain access to their
interfaces as well.

then one may still be left writing code to "route" these interfaces to the
part of the codebase where they are actually needed (especially if getting
it to another library which is itself a dynamically loaded component).

this strategy can be convoluted (ugly initialization code doing a lot of
"plumbing"), and in many cases, it is easier just to be lazy and directly
link against the components.

James Kanze

unread,
Aug 28, 2010, 6:07:42 PM8/28/10
to
On Aug 27, 7:30 am, Goran Pusic <gor...@cse-semaphore.com> wrote:
> On Aug 26, 6:34 pm, James Kanze <james.ka...@gmail.com> wrote:

> > > In fact, I'd go as far as to say that any given system
> > > effectively has a language-agnostic ABI (but they all lean
> > > towards simplicity of C).

> > That used to be true in the distant past, but not today.

> I am sorry, but no. Additional argument to the way I see things: under
> e.g. Windows, there's a myriad of OS interfaces that are exposed
> through COM (e.g. Telephony API, to name but one example). Nobody in
> their right mind is using these interfaces from C, but rather C++.

What does COM have to do with the OS?

> IOW, in theory, C language is incidental to OS interfaces. In
> practice, much less so. :-)

In theory, we really have to start by defining what we mean by
"OS". I'm an old timer---for me, the OS is the part of the code
which has to be executed in kernel mode: things like COM or the
GUI aren't directly part of the OS. (But the border isn't
clear. Many years ago, all of the networking software was built
above the OS as well. Today, I don't know of a kernel that
doesn't have support for TCP/IP built in.) Given that, the
actual ABI must be in assembler, because C doesn't offer any
means of switching from user mode to kernel mode. However,
neither Windows nor any of the Unix I know publish this
interface; they make available a runtime library which provides
a C level interface to it. So from the user's point of view,


the ABI is defined in C.

Of course, addins like COM, the GUI, a data base... or the C++
standard library, may define the interface in any language they
want.

--
James Kanze

Goran Pusic

unread,
Aug 30, 2010, 6:10:46 AM8/30/10
to
On Aug 27, 8:54 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> is there any "particular" reason why people should not use COM interfaces
> from C?...
> this sounds like personal bias, rather than an objective statement, FWIW...

Yes, of course, it's personal opinion on one hand.

On the other, it boils down to: why would you want to bother? It's so
much easier in C++ and you gain strictly nothing by sticking to C.

Goran.

Goran Pusic

unread,
Aug 30, 2010, 6:23:13 AM8/30/10
to
On Aug 29, 12:07 am, James Kanze <james.ka...@gmail.com> wrote:
> In theory, we really have to start by defining what we mean by
> "OS".  I'm an old timer---for me, the OS is the part of the code
> which has to be executed in kernel mode: things like COM or the
> GUI aren't directly part of the OS.

I bet you can beat that, too: OS are software interrupts that are used
to call into... Well, OS :-).

But more seriously, if you take e.g. Telephony API on Windows, sure,
you can use it without COM, but how would you not consider it a part
of the OS? (And there are probably Windows APIs that are strictly COM-
dependent, that is, there is no lower level C interface for them at
all).

And of course, as good people here noted, why would you not consider
assembly?

Goran.

Goran Pusic

unread,
Aug 30, 2010, 6:26:52 AM8/30/10
to

That's just a leftover from the past: 8086 code is faster (or shorter,
don't remember which) with ret x (where "x" is the number of bytes to
pop off the stack when returning), which is possible to do when number
of arguments and their sizes are known up front, and which is what
Pascal compilers on 8086 used to do since Pascal did not know of
variable number of arguments (inhales).

As opposed to C with f(TYPE, ...).

BTW, I remember reading that first Windows code used to be compiled
with quite a bit of Pascal (+asm) code.

Goran.

James Kanze

unread,
Aug 30, 2010, 11:05:32 AM8/30/10
to
On Aug 30, 11:23 am, Goran Pusic <gor...@cse-semaphore.com> wrote:
> On Aug 29, 12:07 am, James Kanze <james.ka...@gmail.com> wrote:

> > In theory, we really have to start by defining what we mean by
> > "OS". I'm an old timer---for me, the OS is the part of the code
> > which has to be executed in kernel mode: things like COM or the
> > GUI aren't directly part of the OS.

> I bet you can beat that, too: OS are software interrupts that
> are used to call into... Well, OS :-).

> But more seriously, if you take e.g. Telephony API on Windows,
> sure, you can use it without COM, but how would you not
> consider it a part of the OS?

What is the telephony API? I've never heard of it, and I've
been doing some pretty low level Windows programming lately.
And if the name is anywhere relevant, how could you consider it
part of the OS?

> (And there are probably Windows APIs that are strictly COM-
> dependent, that is, there is no lower level C interface for
> them at all).

There are certainly programs under Windows whose API is strictly
COM. Or something else completely.

> And of course, as good people here noted, why would you not
> consider assembly?

Because Windows doesn't define the assembler level API.

--
James Kanze

Alf P. Steinbach /Usenet

unread,
Aug 30, 2010, 11:17:44 AM8/30/10
to
* James Kanze, on 30.08.2010 17:05:

> On Aug 30, 11:23 am, Goran Pusic<gor...@cse-semaphore.com> wrote:
>> On Aug 29, 12:07 am, James Kanze<james.ka...@gmail.com> wrote:
>
>>> In theory, we really have to start by defining what we mean by
>>> "OS". I'm an old timer---for me, the OS is the part of the code
>>> which has to be executed in kernel mode: things like COM or the
>>> GUI aren't directly part of the OS.
>
>> I bet you can beat that, too: OS are software interrupts that
>> are used to call into... Well, OS :-).
>
>> But more seriously, if you take e.g. Telephony API on Windows,
>> sure, you can use it without COM, but how would you not
>> consider it a part of the OS?
>
> What is the telephony API? I've never heard of it, and I've
> been doing some pretty low level Windows programming lately.

You might look up RAS.


> And if the name is anywhere relevant, how could you consider it
> part of the OS?

In Windows even the GUI is part of the OS. So much so that at least still in
Windows 2000, as I recall, the thread scheduler interacted with window message
loops; you could affect performance by sprinkling in some window message queue
checking. Since that code reportedly is very very hairy spaghetti it's probably
still that way.

One big annoyance is that DCOM (Distributed COM, sort of remote procedure calls
in a slightly object-oriented way) is so very much part of the OS that if you
stop that service then the OS reboots.

The reason that it's a big annoyance is that much malware has been targeted
directly at DCOM -- and you can't turn it off.


>> (And there are probably Windows APIs that are strictly COM-
>> dependent, that is, there is no lower level C interface for
>> them at all).
>
> There are certainly programs under Windows whose API is strictly
> COM. Or something else completely.

E.g. the shell API is mostly COM based.


>> And of course, as good people here noted, why would you not
>> consider assembly?
>
> Because Windows doesn't define the assembler level API.

Uh, it does. :-)

That's what an ABI means.

Defining that level.

BGB / cr88192

unread,
Aug 30, 2010, 11:47:18 AM8/30/10
to

"Goran Pusic" <gor...@cse-semaphore.com> wrote in message
news:a9e2f4ca-68b6-4f72...@t2g2000yqe.googlegroups.com...

On Aug 27, 8:54 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> is there any "particular" reason why people should not use COM interfaces
> from C?...
> this sounds like personal bias, rather than an objective statement,
> FWIW...

<--


Yes, of course, it's personal opinion on one hand.

On the other, it boils down to: why would you want to bother? It's so
much easier in C++ and you gain strictly nothing by sticking to C.

-->

it is easier, though, if one does a lot of code-processing via automated
tools, and their tools are not smart enough to really deal with C++ syntax
or concepts (such as namespaces, ...). whereas things like scoping via
naming convention is generally easier to handle within a dumb tool.


but, anyways, it all depends a lot on the region of code.

for example, a project may be divided into different regions (or layers),
each with different rules:
for example, lower layers may disallow using C++, and enforce certain
practices WRT modularity and internal dependency management, ...;
middle layer code may be written in C++, and may relax modularity
requirements;
frontend code may even allow other languages, such as C# or Java, ...

so, the bigger factor may well be where in the larger codebase the code is
located.


and, it may so happen that in some of the places where there is the greatest
need to make use of COM-like systems, may also be the areas where the most
rigid practices are in place, which may reasonably exclude things like using
C++ (just as it may enforce modularity practices, disallow
cyclic-dependencies between subsystems, ...).


similarly, coding practices which work well in the <100 kloc range may not
work out as well in the >100 kloc range, and turn disasterous in the Mloc
range, and so these factors need to be considered as well, ...

BGB / cr88192

unread,
Aug 30, 2010, 12:05:03 PM8/30/10
to

"Alf P. Steinbach /Usenet" <alf.p.stein...@gmail.com> wrote in
message news:i5gi2t$eq5$1...@news.eternal-september.org...

if there is one thing I think Windows got right better than most Unix
variants and friends did, it is that they tend to define things down to the
binary level, so although it may be painful to interop at these levels in
many cases, it is at least possible...

in nearly all forms of Unix, most binary details are left up to the
implementation (including flag bit constants, numerical magic values, ...).
only really source-level compatibility is considered, and even then it is a
bit hit or miss as a lot is still only vaguely defined and tend to differ
from one system to another.

granted, there may be preactical reasons for doing this, but it doesn't help
matters much, more so that no comprehensive binary level specifications have
been undertaken.

for example, with Linux (theoretically a single OS), it is a bit hit or miss
if binary code will even work between distros, or between different versions
of the same distro (since many of the library writers see no problem in
making changes to library headers and API's which tend to break binary code,
seeing things like changing structure layouts or magic numbers as "innocent
changes"...).

ideally, people could get all this crap nailed down, but at this point it
seems unlikely...

Ian Collins

unread,
Aug 30, 2010, 3:58:22 PM8/30/10
to
On 08/31/10 04:05 AM, BGB / cr88192 wrote:
> "Alf P. Steinbach /Usenet"<alf.p.stein...@gmail.com> wrote in
> message news:i5gi2t$eq5$1...@news.eternal-september.org...
>> * James Kanze, on 30.08.2010 17:05:
>>>
>>> Because Windows doesn't define the assembler level API.
>>
>> Uh, it does. :-)
>>
>> That's what an ABI means.
>>
>> Defining that level.
>>
>
> if there is one thing I think Windows got right better than most Unix
> variants and friends did, it is that they tend to define things down to the
> binary level, so although it may be painful to interop at these levels in
> many cases, it is at least possible...
>
> in nearly all forms of Unix, most binary details are left up to the
> implementation (including flag bit constants, numerical magic values, ...).
> only really source-level compatibility is considered, and even then it is a
> bit hit or miss as a lot is still only vaguely defined and tend to differ
> from one system to another.

Which is why Solaris and its derivatives is such a breeze to release
code for. Build on the the oldest version you want to support and it
will work on all newer versions. I agree it's a shame Linux didn't
follow that path.

--
Ian Collins

BGB / cr88192

unread,
Aug 30, 2010, 10:28:50 PM8/30/10
to

"Ian Collins" <ian-...@hotmail.com> wrote in message
news:8e2gqu...@mid.individual.net...

yep.

would have been nice...

as is, some of the benefit of open source is lost when all software needs to
be compiled for a particular system...


Nick Keighley

unread,
Aug 31, 2010, 3:15:29 AM8/31/10
to
On 25 Aug, 15:44, Goran Pusic <gor...@cse-semaphore.com> wrote:

> Any compiler provides you with a way to specify what calling
> convention you want from a list of calling conventions chosen by that
> compiler (look for e.g. __cdecl).

you mean *all* compilers provide you with a way of secifying calling
conventions? I find that surprising.

Goran Pusic

unread,
Aug 31, 2010, 4:21:25 AM8/31/10
to
On Aug 31, 9:15 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

Heh, you're probably right :-). Or at least, I see no reason why there
would not be compilers that have calling convention set in stone.

But normally, compilers are prepared for eventualities, so that you
can use calling that fits the HW/SW platform.

Goran.

James Kanze

unread,
Aug 31, 2010, 12:46:39 PM8/31/10
to
On Aug 30, 4:17 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach

+use...@gmail.com> wrote:
> * James Kanze, on 30.08.2010 17:05:
> > On Aug 30, 11:23 am, Goran Pusic<gor...@cse-semaphore.com> wrote:
> >> On Aug 29, 12:07 am, James Kanze<james.ka...@gmail.com> wrote:

> >>> In theory, we really have to start by defining what we
> >>> mean by "OS". I'm an old timer---for me, the OS is the
> >>> part of the code which has to be executed in kernel mode:
> >>> things like COM or the GUI aren't directly part of the OS.

> >> I bet you can beat that, too: OS are software interrupts
> >> that are used to call into... Well, OS :-).

> >> But more seriously, if you take e.g. Telephony API on
> >> Windows, sure, you can use it without COM, but how would
> >> you not consider it a part of the OS?

> > What is the telephony API? I've never heard of it, and I've
> > been doing some pretty low level Windows programming lately.

> You might look up RAS.

Looks like an in house version of SNMP. In other words, not
really part of the OS (but interacting with it).

> > And if the name is anywhere relevant, how could you consider
> > it part of the OS?

> In Windows even the GUI is part of the OS. So much so that at
> least still in Windows 2000, as I recall, the thread scheduler
> interacted with window message loops; you could affect
> performance by sprinkling in some window message queue
> checking. Since that code reportedly is very very hairy
> spaghetti it's probably still that way.

The GUI is a borderline case. Regardless of the system, it does
need some OS support; you can't have just any user process
writing anywhere on the screen (or capturing keystrokes or mouse
clicks that weren't intended for it). From what little I've
seen, it's clear that the boundary between the OS and things
like displaying a button in a window is much higher under
Windows than under Unix (at least Unix with X---I don't know
about Mac). But things like adding a button to a pane in a
Window still aren't really part of the OS. They're part of a
library which uses whatever lower level interfaces the system
provides.

> One big annoyance is that DCOM (Distributed COM, sort of
> remote procedure calls in a slightly object-oriented way) is
> so very much part of the OS that if you stop that service then
> the OS reboots.

:-). Well, it's fairly easy to write a program like that for
Unix, at least if you have root priviledges to install it.
(Many of the applications I've worked on, in fact, did this.)
That doesn't really make them part of the OS.

[...]


> >> And of course, as good people here noted, why would you not
> >> consider assembly?

> > Because Windows doesn't define the assembler level API.

> Uh, it does. :-)

> That's what an ABI means.

> Defining that level.

Yes and no. An ABI does involve defining a number of low level
things, like how struct's are laid out (today---it wasn't always
the case). On the other hand, I've yet to see any Windows
documentation concerning how to call CreateFile (for example)
other than in C.

--
James Kanze

James Kanze

unread,
Aug 31, 2010, 12:54:05 PM8/31/10
to
On Aug 30, 5:05 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "Alf P. Steinbach /Usenet" <alf.p.steinbach+use...@gmail.com> wrote in
> messagenews:i5gi2t$eq5$1...@news.eternal-september.org...

> >* James Kanze, on 30.08.2010 17:05:

[...]


> >>> And of course, as good people here noted, why would you not
> >>> consider assembly?

> >> Because Windows doesn't define the assembler level API.

> > Uh, it does. :-)

> > That's what an ABI means.

> > Defining that level.

> if there is one thing I think Windows got right better than
> most Unix variants and friends did, it is that they tend to
> define things down to the binary level, so although it may be
> painful to interop at these levels in many cases, it is at
> least possible...

I don't see what that buys you. However...

> in nearly all forms of Unix, most binary details are left up
> to the implementation (including flag bit constants, numerical
> magic values, ...). only really source-level compatibility is
> considered, and even then it is a bit hit or miss as a lot is
> still only vaguely defined and tend to differ from one system
> to another.

> granted, there may be preactical reasons for doing this, but
> it doesn't help matters much, more so that no comprehensive
> binary level specifications have been undertaken.

> for example, with Linux (theoretically a single OS), it is a
> bit hit or miss if binary code will even work between distros,
> or between different versions of the same distro (since many
> of the library writers see no problem in making changes to
> library headers and API's which tend to break binary code,
> seeing things like changing structure layouts or magic numbers
> as "innocent changes"...).

This is a real problem. Techically, it's not a problem with the
OS, since most of the libraries are third party, and not part of
the OS, but if you're trying to get something to work, it really
doesn't matter.

Note that Windows is even worse, however. You have to ensure
that all of the libraries were compiled with the same compiler,
using the same options. (The distributed binaries for Boost
didn't work with our system. Nor did those created by another
group in the company, using the same compiler, but slightly
different options.)

> ideally, people could get all this crap nailed down, but at
> this point it seems unlikely...

I fear you're right.

Most commercial libraries seem to realize the importance of
backward compatibility; if your code worked with version x, it
will work with version x+1. So if some new code requires a
newer version of the library, you don't break all of the older
code. I've not found this to be the case with most free
libraries, however. (But there are exceptions both ways.)

--
James Kanze

Alf P. Steinbach /Usenet

unread,
Aug 31, 2010, 12:55:40 PM8/31/10
to
* James Kanze, on 31.08.2010 18:46:

>
> Yes and no. An ABI does involve defining a number of low level
> things, like how struct's are laid out (today---it wasn't always
> the case). On the other hand, I've yet to see any Windows
> documentation concerning how to call CreateFile (for example)
> other than in C.

It's stdcall convention, which is well defined for the things used in the API
(it doesn't extend to C++ RVO, though).

James Kanze

unread,
Aug 31, 2010, 12:57:27 PM8/31/10
to
On Aug 30, 8:58 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 08/31/10 04:05 AM, BGB / cr88192 wrote:

[...]


> Which is why Solaris and its derivatives is such a breeze to release
> code for. Build on the the oldest version you want to support and it
> will work on all newer versions. I agree it's a shame Linux didn't
> follow that path.

I think it's moving that way. At least, I've had less problems
in the last couple of years than previously.

At least with regards to the OS. A lot of the software under
Linux (and to some degree under Solaris and Windows as well) is
third party freeware, which depends on a specific version of
some other third party freeware, ad infinitum.

--
James Kanze

BGB / cr88192

unread,
Aug 31, 2010, 1:06:29 PM8/31/10
to

"Goran Pusic" <gor...@cse-semaphore.com> wrote in message
news:064c1e9c-83fd-4862...@l20g2000yqm.googlegroups.com...

On Aug 31, 9:15 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
> On 25 Aug, 15:44, Goran Pusic <gor...@cse-semaphore.com> wrote:
>
> > Any compiler provides you with a way to specify what calling
> > convention you want from a list of calling conventions chosen by that
> > compiler (look for e.g. __cdecl).
>
> you mean *all* compilers provide you with a way of secifying calling
> conventions? I find that surprising.

<--


Heh, you're probably right :-). Or at least, I see no reason why there
would not be compilers that have calling convention set in stone.

But normally, compilers are prepared for eventualities, so that you
can use calling that fits the HW/SW platform.

-->

yes, this is probably extra true of compilers which may target multiple OS
and CPU architectures, where many things will be set as "sane defaults" for
a target architecture, but may not be internally fixes within the compiler,
and can be effected by all manner of extension keywords...

consider a compiler which targets Win32 and Linux, which may internally
support all of Win32's conventions on Linux, even though Linux doesn't use
them.

now, what if the compiler is ported to Win64 and Linux x86-64? likely the
keywords are still there, and may still do "something", although not
necessarily what is intended (the compiler could complain, ignore it, or
silently do something different and unexpected, such as use a different
calling convention, produce mutilated code, ...).

and if more targets are supported, many other features may be added.

and, if the compiler is extended to support multiple source languages as
well, even more bizarre possibilities exist (the risk of inter-language
syntax/semantic bleedover), ... for example, because several different
languages could use the same parser and compiler machinery (say, with an
internal "lang" modifier or similar to keep them separate and effect other
source-language-specific behavior, but this border being crossed if one
writes code outside the usual borders of a given source language, ...).

example:
__kw_function foo(x):int
{ return((int)(&x)); }
for example, the code above exploiting compiler internals to mix C and
JavaScript syntax...
say, the compiler in question uses '__kw_' as a prefix to escape keywords
(and '__type_' to escape new base-types, '__builtin_' for builtins, ...),
and exploits the JS 'function' keyword and parse logic (the parser not
knowing of any other use for this keyword), and the compiler not checking
that this use is sane, ... (and, whether or not the backend doesn't blow up
is another issue...).


but, granted, single source language, single target, compilers are likely to
not have any of these sorts of "features".


James Kanze

unread,
Aug 31, 2010, 1:24:49 PM8/31/10
to
On Aug 26, 6:55 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "James Kanze" <james.ka...@gmail.com> wrote in message

> news:ef1763bb-d598-49f6...@k10g2000yqa.googlegroups.com...
> On Aug 26, 12:25 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> > "James Kanze" <james.ka...@gmail.com> wrote in message
> >news:13533014-dba5-456f...@l6g2000yqb.googlegroups.com...
> > On Aug 25, 3:44 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:

> yeah.

The only one I've seen which does this is the Microsoft
compiler.

> although granted my experience is mostly limited to Windows (where this
> convention would likely be default as MS uses it),

Most of my experience is Unix. I've only really aborded Windows
in the last year (and only with the Visual Studios).

> and Linux (where generally there is only a single calling
> convention in use, hence no real need to use it...).

I've not seen this under Linux. G++ does have a __attribute__
keyword, but this covers a lot more than linkage. It allows
declaring, for example, that a function never returns, or is
pure. Things so useful for the optimizer that the next version
of the standard will provide a similar mechanism.

Under Windows, this technique is used for things like dllimport
and dllexport as well (since it is necessary), and on Intel
processors, there is an attribute cdecl, which will override any
compile line option telling the compiler to use a different
calling convention (which no one in their right mind would use,
since it means that you can't link with any number of other
programs---although by all rights, the "optional" form should be
the default for C++).

> this notation makes a little more sense IMO than the 'extern
> "lang" ' notation in many cases, as it allows defining the
> calling convention of function pointers, ... which the former
> can't do effectively,

Why not? Function pointers do have language binding as part of
their type; you can't assign the address of a C++ function to a
function pointer with ``extern "C"'' in its type. (At least two
compilers are broken in this regard, however, and don't enforce
the rule: Microsoft VC++ and g++.)

> however, the 'extern "lang" ' notation does have the
> usefulness that it can be applied to an entire block of
> definitions, rather than having to be endlessly repeated for
> each declaration.

> hence:
> void (__stdcall *foo)(int x, double y);

> and:
> extern "C"
> {
> ...
>
> }

Or also:
extern "C" void foo(void* (*)(void*));
Which can only be called with a pointer to an ``extern "C"''
function.

> > in most cases, fastcall can be ignored (it is almost never
> > used for external linkage AFAICT), and thiscall can simply be
> > regarded as a special case of cdecl.
> > this is a major reason for modifier tags like WINAPI and
> > similar: they wrap the calling convention keywords.
> > on 64-bit Windows, there is a single calling convention (Win64);
> > on 64-bit Linux and OSX, there is a single calling convention (AMD64);

> <--
> As is the case under Solaris, HP/UX and AIX. And probably every
> other system around.
> -->

> most non-Windows systems on x86-64 AFAIK use AMD64.

Only those running on AMD 64 bit hardware and the Intel clones
of them. Sparc has completely different conventions, as does
HP/UX on HP's PA based machines. IIRC, 32 bit Linux uses an
adaptation of Intel's Itanium 64 bit conventions.

> admittedly, I personally like Win64's design a little more, as
> AMD64 seems a bit complicated and over-engineered and likely
> to actually reduce performance slightly in common use cases vs
> Win64's design.

> > on 32-bit Linux, in practice pretty much everyone just uses
> > cdecl...

> <--
> On 32-bit Linux, I've never used anything.
> -->

> on 32-bit Linux, there is only a single calling convention in
> single use, so no one needs to... doesn't mean the calling
> convention is not there, only that it is not needed to specify
> it.

Rather that the default is universal. I think the difference is
that under Windows, the default may be something like cdecl, but
many (most) of the OS interface functions use something else.

> > IIRC, MS-DOS was a mess though, with many compilers doing
> > things differently, so code from one compiler would not
> > normally link correctly with code produced by another.

> <--
> Yes and no. All of the C compilers I tried did the same thing.
> All of the C++ compilers were different. But that's the case
> almost universally today as well.
> -->

> there were differences. many C compilers used OMF (as the
> object format), and some used others (including COFF, but this
> was typically for DPMI-based compilers, as well as I think I
> remember there being 32-bit OMF, ...); there were a few others
> as well IIRC.

> although, all this was long ago, and my memory is faded.

Most of the compilers I used under MS-DOS used Microsoft's
object format, which was originally based on Intel's. The one
exception, Intel's own compiler, used the Intel format, but
could link the Microsoft object format as well.

[...]


> but, Windows and x86 (or Windows and x64 / x86-64) represent
> the vast majority of total systems (desktop and laptop at
> least) in use...

You notice that you have to qualify it. I'd be surprised if
there were more Windows than Symbian or VxWorks, in terms of
numbers of machines running the system. And of course, Unix
still dominates servers and large scale embedded systems
(network management, telecoms, etc.).

> Linux and OSX (on x86 or x86-64) are most of the rest.

> ARM and PPC are used in many embedded systems. (not sure the
> OS popularity distribution for embedded systems, from what I
> have seen I would guess: Linux, FreeDOS, and various
> proprietary OS's...).

VxWorks dominates, I think. Except on portable phones, where
Symbian dominates.

> most other architectures and operating systems can be largely
> safely ignored...

Unless you're doing something important: a large scale server,
network management, etc. I've done far more work under Solaris
than under Windows.

--
James Kanze

James Kanze

unread,
Aug 31, 2010, 1:30:50 PM8/31/10
to
On Aug 31, 8:15 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

They're required to by the standard. All compilers are required
to support both ``extern "C"'' and ``extern "C++"''. Most do
this in a standard conformant manner, and don't support anything
else, however.

But it depends on the platform. The Intel architecture has
hardware support for cleaning up the stack when returning from a
function. To use it, however, the function must always be
called with the same number of bytes as arguments; it doesn't
work with varargs. The C standard added the requirement that
when calling a varargs function, a declaration for it must be in
scope, so that one could use the hardware support most of the
time, and skip it when the function used varargs. Historically,
however, this came too late. The intelligent solution is to use
the vararg convention for C, and the hardware support for C++
(which requires a function declaration to be in scope for all
functions), but all modern compilers follow Microsoft rather
than doing this. (The old Zortech C++ compiler did this, using
a different calling convention for C and for C++. And passing
the address of a C++ function to a function expecting a pointer
to a C function would cause a crash.)

--
James Kanze

James Kanze

unread,
Aug 31, 2010, 1:38:34 PM8/31/10
to
On Aug 25, 2:39 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:
> On Aug 25, 3:25 pm, James Kanze <james.ka...@gmail.com> wrote:

> > On Aug 25, 11:28 am, Goran Pusic <gor...@cse-semaphore.com> wrote:

> > > On Aug 25, 9:42 am, Stanis³aw Findeisen <nore...@eisenbits.com> wrote:

> > [...]

> > > I'd say that for a given compiler (version) on a given
> > > platform, there's no difference between a C and a C++
> > > function, except that you need extern "C" to turn off name
> > > mangling that happens with a C++ compiler. So that's why
> > > you have extern "C".

> > And you'd be wrong. At least one compiler I've used used
> > different calling conventions for C and for C++.

> Ugh. Which one and why (if you can be bothered)?

The old Zortech compler. Because C is more broken than C++:-).
Intel has hardware support for cleaning up the stack, provided
the function in question has a fixed number of bytes as
arguments. In pre-standard C, it was usual to call functions
like printf without a declaration in scope, so the compiler had
to assume that all functions were varargs (and thus used the
less efficient convention). C++ has always requires a function
declaration to be in scope in order to call the function, so the
compiler used the hardware support to clean up the stack. (The
results were slightly smaller and slightly faster.)

> To be honest, I can't think of a reason why would any compiler
> match calling conventions betwen C and C++, but that seems a
> most reasonable (only sensible, really) thing to do when using
> extern "C".

When a function is declared ``extern "C"'', it must match the
calling conventions of C.

--
James Kanze

BGB / cr88192

unread,
Aug 31, 2010, 2:05:00 PM8/31/10
to

"James Kanze" <james...@gmail.com> wrote in message
news:82886e17-f45d-44fe...@x25g2000yqj.googlegroups.com...

this usually only pops up when using C++ across library borders though...

if one only uses C-level APIs across these borders, these problems are
greatly reduced, as the "which compiler with which options" issue,
typically, mostly disappears.

but, even then, one has to be fairly rigid about coding practices to avoid
many of the subtle issues which tend to pop up with more "casual" API-design
practices (even things as simple as physically passing and returning
structs, vs sending them as pointers, may foul things up as different
compilers seem to disagree over things like how to pass or return various
types of struct, or over things like how to pad misaligned struct members,
exact size/alignment for struct arrays, ...).

CC-A: expects a pointer as a hidden first arg for returning a given struct;
CC-B: expects this struct to be put in registers (say, the < 12-byte
EAX/ECX/EDX interpretation).

CC-A: expects to pass an internal reference to a struct on the stack;
CC-B: expects the whole struct to be placed on the stack.
...

but, otherwise, at the C level things tend to be much more solid, whereas
the C++ level is an inter-compiler mess of sorts.


except WRT Cygwin, which adds its own bizarreness, which IMO as a matter of
policy should not be used to compile DLL's... (MinGW and MSVC are fairly
safe though IME...).

however, most open-source code is difficult to get to build on even on
Cygwin, much less MinGW, and MSVC typically requires a lot of internal
tweaking (as, sadly, even most "portable" OSS code tends to use the
occasional GCC'ism here or there...).


>> ideally, people could get all this crap nailed down, but at
>> this point it seems unlikely...
>
> I fear you're right.
>
> Most commercial libraries seem to realize the importance of
> backward compatibility; if your code worked with version x, it
> will work with version x+1. So if some new code requires a
> newer version of the library, you don't break all of the older
> code. I've not found this to be the case with most free
> libraries, however. (But there are exceptions both ways.)
>

yes.

the problem comes down a lot to API design...
to keep everything from breaking requires fairly careful API design and
maintainence, which many/most OSS libraries don't seem to care about
bothering with...

not everyone wants to write libraries, say, with the look and feel of
OpenGL, although GL is a good example of a library/system which has done
notably well at avoiding versioning issues...

DirectX doesn't do as well, since an app usually has to consider issues
related to the particular version of the library they are developing
against, API versions, ..., and in a few cases DX has dropped little-used
features, potentially breaking any (likely rare) apps which may have
depended on them.

but, even then, DX is still a lot better than many OSS libraries in these
regards (many which make little real effort to address the matter of
versioning, ...).


but, yes, keeping one's bit flags, magic values, struct layouts, ... "set in
stone" (or avoiding them altogether), is a little more effort (and many OSS
libs don't bother).

directly using C++ across a library boundary is a practice I personally
think is nearly the opposite extreme, as it provides almost no protection
from the matters of compiler-dependent features and from versioning (since
something as "innocent" as adding a new method to a class may essentially
change the vtable layouts of both the class and any other class which
inherits from it, thus breaking binary interop, ...).


even in naively designed codebases, this option may pop up, as say changing
something in a header and rebuilding code may leave much of the rest of the
codebase as "stale" and causing bugs, requiring either that code be rebuilt
if headers change (an extreme time-wasting hassle, especially for Mloc
codebases...), or doing a "clean" build (deleting all objects and binary
code) if any significant changes are made.

however, recently with my coding practices, I have largely avoided both of
the above (I neither track header changes, nor usually need to bother with
clean builds).


or such...


Goran

unread,
Aug 31, 2010, 2:25:23 PM8/31/10
to
On Aug 30, 5:05 pm, James Kanze <james.ka...@gmail.com> wrote:
> What is the telephony API?  I've never heard of it, and I've
> been doing some pretty low level Windows programming lately.

http://msdn.microsoft.com/en-us/library/ms734273%28VS.85%29.aspx or
http://www.google.be/search?q=windows+Telephony+API. Notably, the TAPI
3 part is pure COM.

Goran.

BGB / cr88192

unread,
Aug 31, 2010, 3:36:05 PM8/31/10
to

"James Kanze" <james...@gmail.com> wrote in message
news:71f06c7e-ff6f-42a3...@d8g2000yqf.googlegroups.com...

On Aug 26, 6:55 pm, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> "James Kanze" <james.ka...@gmail.com> wrote in message

> news:ef1763bb-d598-49f6...@k10g2000yqa.googlegroups.com...
> On Aug 26, 12:25 am, "BGB / cr88192" <cr88...@hotmail.com> wrote:
> > "James Kanze" <james.ka...@gmail.com> wrote in message
> >news:13533014-dba5-456f...@l6g2000yqb.googlegroups.com...
> > On Aug 25, 3:44 pm, Goran Pusic <gor...@cse-semaphore.com> wrote:

> yeah.

<--


The only one I've seen which does this is the Microsoft
compiler.

-->

GCC and most other compilers which support Windows also do this.


> although granted my experience is mostly limited to Windows (where this
> convention would likely be default as MS uses it),

<--


Most of my experience is Unix. I've only really aborded Windows
in the last year (and only with the Visual Studios).

-->

yeah.
I develop on both Windows and Linux, but anymore mostly on Windows, since
this is where most of the potential users are.

however, I use an "unusual" build setup, typically mixing MSVC and the GNU
toolchain (via Cygwin), which I worry sometimes may hinder others' from
using the code (since they would have to figure out how to get this
build-setup to work).

but, the problem is that building from the commandline is notably less
"nice" with MS's tools than with the GNU tools (MS's nmake sucks, ...).

also lame is that I often don't get around with keeping all of the
Linux-specific (and non-MSVC) code and Makefile's up to date, ... so usually
trying to get a Linux build to work (when I get around to it usually
requires several hours or more trying to get everything to build and work
again).


> and Linux (where generally there is only a single calling
> convention in use, hence no real need to use it...).

<--


I've not seen this under Linux. G++ does have a __attribute__
keyword, but this covers a lot more than linkage. It allows
declaring, for example, that a function never returns, or is
pure. Things so useful for the optimizer that the next version
of the standard will provide a similar mechanism.

-->

"no real need to use it" also implies "will rarely/never be seen" or "can be
assumed not to exist".
one could try and see what happens if they try to use __stdcall on 32-bit
Linux, and whether or not the compiler will accept it or what the exact
result will be, I don't know...

<--


Under Windows, this technique is used for things like dllimport
and dllexport as well (since it is necessary), and on Intel
processors, there is an attribute cdecl, which will override any
compile line option telling the compiler to use a different
calling convention (which no one in their right mind would use,
since it means that you can't link with any number of other
programs---although by all rights, the "optional" form should be
the default for C++).

-->

yes.

there is also __declspec, which MSVC uses.

my compiler ended up having to support both __declspec and __attribute__
modifiers, since it partly emulates both MSVC and GCC (this itself is a bit
of a mess...). this is partly because many headers will not do anything
"sane" if not emulating a compiler they know about.

#if defined(__GNUC__)
...
#elif defined(_MSC_VER)
...
#elif defined(__WATCOMC__)
...
#else
#error "GASP! What is going on here!"
#endif

and, going and having to fiddle with all these headers to add specifics for
a new compiler would be a problem.

so, it is easier to try to emulate whatever other compiler is being used for
building code (using my own defines to identify my compiler in "emulation
mode"), and then try to sort out the mountains of crud which typically
results from this (IOW, the "side compiler" strategy...).


> this notation makes a little more sense IMO than the 'extern
> "lang" ' notation in many cases, as it allows defining the
> calling convention of function pointers, ... which the former
> can't do effectively,

<--


Why not? Function pointers do have language binding as part of
their type; you can't assign the address of a C++ function to a
function pointer with ``extern "C"'' in its type. (At least two
compilers are broken in this regard, however, and don't enforce
the rule: Microsoft VC++ and g++.)

-->

possibly, but I was unaware of this working in the typical (inline) case, as
I would have thought it would require either defining them as proper
variables or as typedef's...

example:
fptr=((void *(__stdcall *)(HANDLE, LPCSTR))GetProcAddrss(windll,
"GetProcAddress"))(windll, "CreateWindowEx");

although a contrieved example, this sort of usage pattern does pop up
sometimes (usually in nasty code which is better off wrapped).

most commonly in my case, this sort of usage pattern pops up when calling
from statically compiled code into dynamically compiled code, since for
(likely fairly obvious) reasons, one can't call directly from a
statically-compiled piece of code into code which does not exist until
run-time.

this is also one of the few nasty places where I need glue-code to interface
with script languages (another place being to expose C the contents of
structs to dynamically-typed languages, ...), as the machinery for doing all
this transparently is still not complete.

actually, implicit C -> dynamic-typed language calls present a few other
hassles, such as needing to identify another function/prototype/... as a
"template" for the function pointer to return (although, many wrappers can
use themselves as the template, presuming they exist and are C functions).

admittedly, I don't really trust the code which does all this, and it is not
well tested, and so the strategy of using an API call to perform the
function call is preferable, rather than trying to call the thing via a
function pointer.

t=dyCall2("someDynamicFunction", x, y); //safer, as it avoids internal
thunk-generation nastiness

the above also works in wrappers, but requires extra glue-code if the
objective is a function pointer to use as a callback or similar. current
"best practice" is to not try to use callbacks with dynamically typed code,
or at least until better "proven safe", or at least "proven to generally
work"...


> however, the 'extern "lang" ' notation does have the
> usefulness that it can be applied to an entire block of
> definitions, rather than having to be endlessly repeated for
> each declaration.

> hence:
> void (__stdcall *foo)(int x, double y);

> and:
> extern "C"
> {
> ...
>
> }

<--


Or also:
extern "C" void foo(void* (*)(void*));
Which can only be called with a pointer to an ``extern "C"''
function.

-->

yes, the "declare a proper variable" case from before.
I have no idea if this works from casts though, or what the exact notation
would be.


> > in most cases, fastcall can be ignored (it is almost never
> > used for external linkage AFAICT), and thiscall can simply be
> > regarded as a special case of cdecl.
> > this is a major reason for modifier tags like WINAPI and
> > similar: they wrap the calling convention keywords.
> > on 64-bit Windows, there is a single calling convention (Win64);
> > on 64-bit Linux and OSX, there is a single calling convention (AMD64);

> <--
> As is the case under Solaris, HP/UX and AIX. And probably every
> other system around.
> -->

> most non-Windows systems on x86-64 AFAIK use AMD64.

<--


Only those running on AMD 64 bit hardware and the Intel clones
of them. Sparc has completely different conventions, as does
HP/UX on HP's PA based machines. IIRC, 32 bit Linux uses an
adaptation of Intel's Itanium 64 bit conventions.

-->

I did say "on x86-64" here, which naturally excludes things like SPARC, ...

IIRC, g++ on Win32 uses the same C++ ABI as on Linux, hence, it doesn't play
well with MSVC for C++ code, hence creating a wall if one is using libraries
compiled with both compilers together...


> admittedly, I personally like Win64's design a little more, as
> AMD64 seems a bit complicated and over-engineered and likely
> to actually reduce performance slightly in common use cases vs
> Win64's design.

> > on 32-bit Linux, in practice pretty much everyone just uses
> > cdecl...

> <--
> On 32-bit Linux, I've never used anything.
> -->

> on 32-bit Linux, there is only a single calling convention in
> single use, so no one needs to... doesn't mean the calling
> convention is not there, only that it is not needed to specify
> it.

<--


Rather that the default is universal. I think the difference is
that under Windows, the default may be something like cdecl, but
many (most) of the OS interface functions use something else.

-->

yep.

> > IIRC, MS-DOS was a mess though, with many compilers doing
> > things differently, so code from one compiler would not
> > normally link correctly with code produced by another.

> <--
> Yes and no. All of the C compilers I tried did the same thing.
> All of the C++ compilers were different. But that's the case
> almost universally today as well.
> -->

> there were differences. many C compilers used OMF (as the
> object format), and some used others (including COFF, but this
> was typically for DPMI-based compilers, as well as I think I
> remember there being 32-bit OMF, ...); there were a few others
> as well IIRC.

> although, all this was long ago, and my memory is faded.

<--


Most of the compilers I used under MS-DOS used Microsoft's
object format, which was originally based on Intel's. The one
exception, Intel's own compiler, used the Intel format, but
could link the Microsoft object format as well.

-->

fair enough...

[...]
> but, Windows and x86 (or Windows and x64 / x86-64) represent
> the vast majority of total systems (desktop and laptop at
> least) in use...

<--


You notice that you have to qualify it. I'd be surprised if
there were more Windows than Symbian or VxWorks, in terms of
numbers of machines running the system. And of course, Unix
still dominates servers and large scale embedded systems
(network management, telecoms, etc.).

-->

servers and embedded systems represent different domains...

a lot depends on if one is intending the eventual target use of the app to
be:
on a server somewhere;
being used by an end-user;
on someones' cellphone;
in their microwave;
...

most of my experience is with desktop/end-user targetted software, and here
Windows is dominant...


> Linux and OSX (on x86 or x86-64) are most of the rest.

> ARM and PPC are used in many embedded systems. (not sure the
> OS popularity distribution for embedded systems, from what I
> have seen I would guess: Linux, FreeDOS, and various
> proprietary OS's...).

<--


VxWorks dominates, I think. Except on portable phones, where
Symbian dominates.

-->

fair enough.

most of my (limited) exposure to embedded systems has been with things like
Linksys routers and with Mizu and some other PRC-manufactured devices (which
often use Linux AFAICT).

granted, I am not sure where most devices or manufactured, or what the
largest manufacturing statistics tend to be.

(just as a wild guess from personal experience, I would think the PRC
manufactures most of the devices I see around, and what little I have heard
implies that a stripped down Linux kernel is most popular there, but really
I don't know... and most of these devices are not terribly convinient to
just go and look at and try to figure out what sort of OS or HW they are
running...).


> most other architectures and operating systems can be largely
> safely ignored...

<--


Unless you're doing something important: a large scale server,
network management, etc. I've done far more work under Solaris
than under Windows.
-->

fair enough, but I have never really done much related to larger-scale
systems, since these are generally the sole property of people/companies/...
who actually have money...

otherwise, one may run a server which is basically just a Win XP laptop or
similar which is left always running and is maybe rebooted every so often,
like if it starts bogging down or crashes or whatever...

luckily, most often if XP crashes it will reboot anyways, minimizing the
need for manual intervention most of the time (except if it gets stuck on a
blue-screen or similar...).

Jorgen Grahn

unread,
Sep 1, 2010, 3:15:33 AM9/1/10
to
On Tue, 2010-08-31, BGB / cr88192 wrote:
>
> "Ian Collins" <ian-...@hotmail.com> wrote in message
> news:8e2gqu...@mid.individual.net...
>> On 08/31/10 04:05 AM, BGB / cr88192 wrote:
...

>>> if there is one thing I think Windows got right better than most Unix
>>> variants and friends did, it is that they tend to define things down to
>>> the
>>> binary level, so although it may be painful to interop at these levels in
>>> many cases, it is at least possible...
>>>
>>> in nearly all forms of Unix, most binary details are left up to the
>>> implementation (including flag bit constants, numerical magic values,
>>> ...).
>>> only really source-level compatibility is considered, and even then it is
>>> a
>>> bit hit or miss as a lot is still only vaguely defined and tend to differ
>>> from one system to another.
>>
>> Which is why Solaris and its derivatives is such a breeze to release code
>> for. Build on the the oldest version you want to support and it will work
>> on all newer versions. I agree it's a shame Linux didn't follow that
>> path.
>>
>
> yep.
>
> would have been nice...
>
> as is, some of the benefit of open source is lost when all software needs to
> be compiled for a particular system...

[I'm not sure this is always correct -- at least my systems come
with legacy libc/libstdc++ versions, and if your packages say they
require them, they will be installed. That should cover a few
years.]

I'd say one benefit of open source is that there *can be* different
systems. You have *BSDs and Linuxes for all possible tastes and
architectures.

Windows seems so stable partly because they're locking you to an
obsolete architecture (Intel x86). They were late with AMD64 and my
company still runs new machines in 32-bit mode -- presumably because
too much third-party closed-source software sees that as "the Windows
ABI".

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Ian Collins

unread,
Sep 1, 2010, 5:01:01 AM9/1/10
to
On 09/ 1/10 07:15 PM, Jorgen Grahn wrote:
> On Tue, 2010-08-31, BGB / cr88192 wrote:
>>
>> "Ian Collins"<ian-...@hotmail.com> wrote in message
>> news:8e2gqu...@mid.individual.net...
>>> On 08/31/10 04:05 AM, BGB / cr88192 wrote:
> ....

>>>> if there is one thing I think Windows got right better than most Unix
>>>> variants and friends did, it is that they tend to define things down to
>>>> the
>>>> binary level, so although it may be painful to interop at these levels in
>>>> many cases, it is at least possible...
>>>>
>>>> in nearly all forms of Unix, most binary details are left up to the
>>>> implementation (including flag bit constants, numerical magic values,
>>>> ...).
>>>> only really source-level compatibility is considered, and even then it is
>>>> a
>>>> bit hit or miss as a lot is still only vaguely defined and tend to differ
>>>> from one system to another.
>>>
>>> Which is why Solaris and its derivatives is such a breeze to release code
>>> for. Build on the the oldest version you want to support and it will work
>>> on all newer versions. I agree it's a shame Linux didn't follow that
>>> path.
>>
>> would have been nice...
>>
>> as is, some of the benefit of open source is lost when all software needs to
>> be compiled for a particular system...
>
> [I'm not sure this is always correct -- at least my systems come
> with legacy libc/libstdc++ versions, and if your packages say they
> require them, they will be installed. That should cover a few
> years.]
>
> I'd say one benefit of open source is that there *can be* different
> systems. You have *BSDs and Linuxes for all possible tastes and
> architectures.

You have missed the point of this off topic ramble. The gripe was
incompatibilities between versions of the same OS, not between different
OSs.

--
Ian Collins

BGB / cr88192

unread,
Sep 1, 2010, 1:11:17 PM9/1/10
to

"Ian Collins" <ian-...@hotmail.com> wrote in message
news:8e6j2e...@mid.individual.net...

yeah...

WinXP can run software all the way back to DOS years, and Vista/Win7 can run
most software back to the Win95 timeframe (and still older software, but it
requires an emulator).


and, yes, customization is good.
however, needlessly breaking old code and effectively requiring code to be
recompiled for a particular version of a particular distro is limited.

this essentially takes away much of the advantage of rapidly distributing
binary code, which is about the only real way most end users are likely to
understand how to install software. this effectively puts much of the weight
of distrubuting binary packages into the hands of the people creating and
maintaining the distributions (the rise of people using "package managers"
as their main way of getting software).

another problem (even for people who understand the OS) is that many larger
packages are a *PAIN* to get built, and worse yet, if one builds a new
version of something and installs it, it also holds the risk of essentially
breaking the OS due to versioning issues, ... the strategy then is to wait
for the next version of the distro, and then "upgrade".

so, from the POV of an end user, they almost may as well just be using an
iPhone or iPad where all software needs to be gained from Apple Store and so
on...


most of the blame I suspect is best put on many of the end-developers, many
who don't follow even basic versioning practices:
don't change anything in the public API unless it is critical to do so.

don't add fields to structs or move them around to make them nicer (or,
OTOH, avoid using structs or complex data types in public API's);
don't needlessly change numerical variables (reorganizing flag bit patterns,
changing around magic numbers, ...);
don't notably change the behavior of API calls (or, worse yet, change their
function signatures...);
...


but, I suspect many of this is made harder for many libraries, as their
public API is often just them directly exposing the innards of the library,
rather than designing a (separate) external API for the thing (and keeping
all of the library internals essentially hidden behind an impassable wall).

but, in a sense, this impassable-wall design is needed to help avoid binary
versioning issues.

part may also be developer mindset "opensource means one can rebuild from
source", which is taken to relegate the importance of binary compatibility
to being a concern only for "closed-source" systems.


for example, Win7 is architecturally *very* different from Win95, yet Win95
software still generally works.
MS is probably doing something right...


or such...


Jorgen Grahn

unread,
Sep 3, 2010, 7:11:43 AM9/3/10
to

I don't think I really missed it -- I counted all the different
releases of the different Linux distributions as "versions of the same
OS".

I should not have brought in the BSDs, perhaps.

0 new messages