1. Cause the name of the function to be
in a form that C can recognize (i.e.,
inhibit name-mangling, or the equivalent.)
2. Cause the code for the function to expect
C calling conventions, rather than C++.
There are many situations where you care about
2, but not about 1. In particular, if you are
passing a C++ function as a call-back to a C
library, there is no need for C to recognize the
name of the function, since it will never see
the name, anyway, only a function pointer.
(I'm assuming that the function is not a non-static
member function.)
Unfortunately, C++ doesn't currently have a
way to say 2 without 1. This means, for instance,
that you can't define a call-back function using
a template.
I can't think of any reason for the lack of a way to
specify C-style argument passing alone, without
inhibiting name-mangling, except that it didn't occur
to the language designers that
it might be useful.
Is there any (non-religious) issue that arises if
you specify C-style function calling without having
C-style names?
One obvious use would be the ability to have
templatized classes whose objects spawn a thread
(given that the popular thread libraries are C, not C++.)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
> As I understand it, the extern "C"
> specification for a C++ function
> does two things:
>
> 1. Cause the name of the function to be
> in a form that C can recognize (i.e.,
> inhibit name-mangling, or the equivalent.)
>
> 2. Cause the code for the function to expect
> C calling conventions, rather than C++.
Uhmm... had no idea about 2 which is why I used to pass pointers to C++
functions for C callbacks and didn't worried about it. If what you say is
true I suspect my code walks on UB then.
> One obvious use would be the ability to have
> templatized classes whose objects spawn a thread
> (given that the popular thread libraries are C, not C++.)
I would sugest to use boost.thread or at least look and see what it does in
order to solve the same problem (boost.thread should use pthreads on POSIX
platforms and to pthread_create I suspect it's the function you want to
call with a C++ function callback).
--
Dizzy
On Mon, 11 Jun 2007 09:19:53 CST, Alan McKenney
<alan_mc...@yahoo.com> wrote:
>Is there any (non-religious) issue that arises if
>you specify C-style function calling without having
>C-style names?
>
>One obvious use would be the ability to have
>templatized classes whose objects spawn a thread
>(given that the popular thread libraries are C, not C++.)
Since you mention templates specifically, there is at least one
non-religious issue: the C++ standard forbids declaring template
functions with C linkage (see section 14.4).
I'm not sure that I can follow all the reasons for this decision
because they are beyond my grasp; however, I'm sure they have nothing
to do with religion. ;)
--
Bob Hairgrove
NoSpam...@Home.com
The implementations that I know (Windows, Unix) have the same
calling conventions for both C and C++ when global functions
are called, and you can easily pass a ptr to a C++ function
with POD parameters and return value as a C function ptr.
The only problem you can have mixing C and C++ is exceptions,
because, unfortunately, the C callers cannot catch an exception
thrown in a C++ callee.
There is no reason to have different calling conventions
for functions in C and C++, but I don't know if it's a part
of the C++ standard.
Yet, compiler makers from Sun have a different opinion:
$ cat test.cc
#include <signal.h>
struct X { static void hand(int); };
int main() { signal(SIGINT, X::hand); };
$ CC -V
CC: Sun C++ 5.8 2005/10/13
$ CC -c -o /dev/null test.cc
"test.cc", line 3: Warning (Anachronism): Formal argument 2 of type
extern "C" void(*)(int) in call to std::signal(int, extern "C" void(*)
(int)) is being passed void(*)(int).
1 Warning(s) detected.
Luckily the warning can be turned off:
$ CC -erroff=badargtype2w -c -o /dev/null test.cc
$ <compilation succeeded>
(Religious = having to do with some people's idea of how a computer
language ought to be, or how one ought to program.)
The practical reason given for forbidding template functions with C
linkage is the same as for forbidding (static) class functions with
C linkage: the name in C++ is not a legal function name in C, so
you can't use the un-mangled name. (And there's no transparent way to
turn a template function's name into a legal C function name.)
In other words, it is not the C calling conventions, but
the issue of function naming that is the problem.
The point of my question is precisely this: would it cause some
problem with the C++ language (besides possibly offending some
purists)
if the language were changed to add the ability to specify that
a function should obey the C implementation's calling conventions
without necessarily making it callable by name from C?
I don't see any, but then, I'm not a C++ guru.
(Disciple, maybe, but not guru.)
On Tue, 12 Jun 2007 10:22:43 CST, Alan McKenney
<alan_mc...@yahoo.com> wrote:
>In other words, it is not the C calling conventions, but
>the issue of function naming that is the problem.
I'm not sure what you mean by "calling conventions", then. You can
certainly export any non-local static functions; you can even change
the exported name on some operating systems if the function is in a
shared library, e.g. using a DEF file to create a DLL in Windows
(perhaps there are similar utilities on other OS's?) Also, if you
know how the name is exported (i.e. how it is mangled), you can
certainly call it from a C function in some other code. You just have
to deal with the extra decorations.
If you need to call a C++ function from a C module, you'll probably
need to wrap it in a utility function anyway, especially if it can
throw an exception, as someone else already pointed out.
--
Bob Hairgrove
NoSpam...@Home.com
This does not mean that the calling conventions are different.
The compiler doesn't allow you to pass a function ptr
of different type, just like any decent C or C++ compiler.
You can try to pass a comparison function with a different
signature to qsort and see what happens.
The calling conventions are usually the method of passing the
arguments, obtaining the result and managing the stack.
If the calling conventions are the same for C and C++,
very probably you can pass a C++ function ptr instead of
a C function ptr using a cast, and this will work as expected.
When you pass a pointer, the name mangling of C++ doesn't make
any difference during execution.
In a rare case when the ptrs have different size, you would
get a compiler warning. Anyway, I would first see the assembly
output of the compiler, and put a breakpoint in a callback
when debugging, to see that everything is OK.
By "calling conventions" I mean how arguments are passed,
return values returned, the return address(es) are supplied
and, on some systems, what instruction is used to call the
function. Mixed-language programmers become quickly (and
painfully!) aware of these issues.
There is no reason why the C compiler and the C++ compiler
(even from the same vendor) have to do these things the same
way and there may be good reasons not to; in any case,
the Standard does not require it. Instead, it supplies
the concept of POD and extern "C" to allow programmers to
deal with the differences in a portable fashion.
Passing a pointer to a C++ function to a C function is,
as far as I know, Undefined Behavior, unless the C++ function
was declared as extern "C". It works on most platforms I am
aware of because most vendors try to re-use as much code
between C and C++ as possible, but it is not portable.
My wish is for a way to make this portable, but without the
restrictions that come from the additional (and in this case
unnecessary) feature of extern "C": making the name visible
to C.
> By "calling conventions" I mean how arguments are passed,
> return values returned, the return address(es) are supplied
> and, on some systems, what instruction is used to call the
> function. Mixed-language programmers become quickly (and
> painfully!) aware of these issues.
Indeed. I have been there. But I think we are in a very small minority.
Also I find that not every C++ compiler seems to take notice of the issue.
Recent versions of the Sun Studio compiler spot such mismatches and give a
warning, but the GNU compiler does not. I did raise a bug report to the
gcc/g++ people about this but unfortunately because the issue is a little
esoteric (and best appreciated by people that have to do mixed language
programming) the issue was not understood and was closed. So the issue is
still there in g++ if you want to take a look.
>
> There is no reason why the C compiler and the C++ compiler (even from
> the same vendor) have to do these things the same way and there may be
> good reasons not to;
Indeed, and I find that were there are differences it tends to be in
environments that are open about their support for mixed language
programming. C++, C and FORTRAN seem the most common combinations but I
have seen the issue crop up with C++, C and Pascal as well (on VAX
machines).
> Passing a pointer to a C++ function to a C function is, as far as I
> know, Undefined Behavior, unless the C++ function was declared as extern
> "C". It works on most platforms I am aware of because most vendors try
> to re-use as much code between C and C++ as possible, but it is not
> portable.
In theory yes, in practise this does seem to work everywhere. Maybe some
one can quote an environment where it doesn't....
> My wish is for a way to make this portable, but without the restrictions
> that come from the additional (and in this case unnecessary) feature of
> extern "C": making the name visible to C.
Sounds good to me but I bet this will be a low priority with the stds
people, given that in practise things work as they are.
--
Andrew Marlow http://www.andrewpetermarlow.co.uk
There is an emerald here the size of a plover's egg!
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
> > My wish is for a way to make this portable, but without the restrictions
> > that come from the additional (and in this case unnecessary) feature of
> > extern "C": making the name visible to C.
>
> Sounds good to me but I bet this will be a low priority with the stds
> people, given that in practise things work as they are.
I'm not holding my breath.
But no one has addressed my original question:
Would adding such a feature to the language cause problems?
E.g., breaking type safety, making exceptions substantially harder
to implement, break existing (conformant) code, etc.
-- Alan McKenney
--
The calling convention is an implementation detail and it can vary wrt
different architectures. Some architecture manuals outline possible calling
conventions for the C language.
The calling convention can be a big issue when your trying to mix different
languages. For instance, if you want to create a thread synchronization
abstraction in an external assembly language library that is going to be
used by C programs... Well, you need to do research into the arch(s) AND
the
compilers your targeting... You can usually find out some sort of
"standard"
way of creating a calling convention for C. Therefore, for that
architecture, and compiler, you can build a version of your asm library
which adheres to their C calling convention.
> [] no one has addressed my original question:
>
> Would adding such a feature to the language cause problems?
>
> E.g., breaking type safety, making exceptions substantially harder
> to implement, break existing (conformant) code, etc.
Based on the responses (and non-responses) to this, I'm
going to conclude:
1. There's no obvious problem with adding such a feature,
beyond the usual problems with adding any feature.
2. There's no pressure to add such a feature, because on all
of the popular implementations, passing a C++ (static/global)
function pointer to a C function works without any special
syntax.
In fact, it works sufficiently well that most people are not
aware that there is a (potential) issue.
3. It's clear from other postings that other people *are* passing
C++ static member (and template function) pointers to C
libraries,
so the interest is there. They just ignore the warnings and it
works.
4. At this rate, the requirement that C++ function pointers can be
passed to C libraries, with no special constructs, is fast
becoming a de-facto part of the Standard, much like the
assumption
of a flat address space.
It may not be officially part of the Standard, but no
implementation will succeed commercially if this doesn't work.
> 3. It's clear from other postings that other people *are* passing
> C++ static member (and template function) pointers to C
> libraries,
> so the interest is there. They just ignore the warnings and it
> works.
Well, that's what most people do but I do take the warning from the
solaris compiler seriously and go via an intermediate C function rather
than ignore the warning or cast it away. It's a pity I have not come
across any other compilers that issue the warning. I have not tried the
Comeau compiler on this one. Can anyone else comment on how Comeau handles
it?
> 4. At this rate, the requirement that C++ function pointers can be
> passed to C libraries, with no special constructs, is fast
> becoming a de-facto part of the Standard, much like the
> assumption
> of a flat address space.
Hmm, I would not say it is de-facto, it just hasn't rcvd enough attention
from compiler writers ad this lack of attention means it works the way
most people want it to anyway.
--
Andrew Marlow http://www.andrewpetermarlow.co.uk
There is an emerald here the size of a plover's egg!
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]