Topic: empty parameter list and extern "C


Author: MikeAlpha@NoSpam_csi.com (Martin Aupperle)
Date: Fri, 23 Feb 2001 13:52:36 CST
Raw View
On Thu, 22 Feb 2001 19:32:10 GMT, Jack Klein <jackklein@spamcop.net>
wrote:

>
>Understand that C++ does not guarantee interoperability with code
>compiled by a C compiler, or even by the same compiler in its C mode,
>if it has one.  The intent is to provide this capability if possible,
>but all that extern "C" is guaranteed to do is provide C linkage.
>
I understand. So, please look at the following scenario:

1.)  I have a very old and mean C-Library (i.e. one that is compiled
with a C-compiler). It exposes a header file foo.h that declares a
function f like this:

 void f();

2.) Since it is a C-Library, I conclude that f can (syntactically) be
called with arbitrary arguments. Any C-Program that includes foo.h
should be able to do so.

3.) But I have a C++ program and want to use the library. Therefore I
say

 extern "C"
 {
   #include "foo.h"
 }

Now I have a function  f declared and can use it. BUT NOT with
arbitrary parameters!

4.) It is also not possible to declare f myself, as for example like
this

 extern "C" void f(...);

because then I cannot include foo.h with all the rest of the functions
any more. (Overloading is not possible with extern "C" - that's
understandable)..


So - what is the solution? I probably can introduce a cpp-file that
does nothing but declare f like in 4.), define another function f2
like

 void f2(...);

that does nothing except calling f. But will the parameters be
correctly passed? I think not necessarily, because f2 has c++ linkage
and f has c linkage.


------------------------------------------------
Martin Aupperle
MikeAlpha@NoSpam_csi.com
(remove NoSpam_)
------------------------------------------------

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Sun, 25 Feb 2001 00:48:52 GMT
Raw View
Martin Aupperle wrote:
>
> On Thu, 22 Feb 2001 19:32:10 GMT, Jack Klein <jackklein@spamcop.net>
> wrote:
>
> >
> >Understand that C++ does not guarantee interoperability with code
> >compiled by a C compiler, or even by the same compiler in its C mode,
> >if it has one.  The intent is to provide this capability if possible,
> >but all that extern "C" is guaranteed to do is provide C linkage.
> >
> I understand. So, please look at the following scenario:
>
> 1.)  I have a very old and mean C-Library (i.e. one that is compiled
> with a C-compiler). It exposes a header file foo.h that declares a
> function f like this:
>
>         void f();
>
> 2.) Since it is a C-Library, I conclude that f can (syntactically) be
> called with arbitrary arguments. Any C-Program that includes foo.h
> should be able to do so.

Syntactically, yes. Semantically, no. According to the current C
standard, it's undefined behavior to call f() with arguments whose
number and promoted types are incompatible with those of the parameters
in the definition of f().

> 3.) But I have a C++ program and want to use the library. Therefore I
> say
>
>         extern "C"
>         {
>           #include "foo.h"
>         }
>
> Now I have a function  f declared and can use it. BUT NOT with
> arbitrary parameters!
>
> 4.) It is also not possible to declare f myself, as for example like
> this

If foo() does in fact take no arguments, you should change "foo.h" to
declare it as

 void f(void);

This is legal in C++, and means the same thing as in C. If foo() does in
fact take a fixed number of arguments, declare it with that number of
arguments. If the code using foo() takes advantage of the fact that C
used to allow discrepances between the arguments in a function call and
the parameters of the corresponding function definition, you may be out
of luck, since that's equally illegal in modern C++ as in modern C.
Offhand I see no easy way to trick a modern compiler into cooperating
with such a discrepancy. You'd have to find a compiler with a "k&r"
option that produces modules linkable to code compiled without that
option.

If "foo.h" is inaccessible, you will either have to write your own
replacement for it with a different name, or write suitably defined
wrapper functions, as you've already figured out. One thing you don't
have to worry about is the impossibility of wrapping a function defined
with an '...'. Such a function cannot be legally called using a
declaration as "void f();", neither in C nor in C++.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: comeau@panix.com (Greg Comeau)
Date: Sun, 25 Feb 2001 01:22:13 GMT
Raw View
In article <3a968230.533654664@news.nikoma.de>,
Martin Aupperle <MikeAlpha@NoSpam_csi.com> wrote:
>On Thu, 22 Feb 2001 19:32:10 GMT, Jack Klein <jackklein@spamcop.net>
>wrote:
>>Understand that C++ does not guarantee interoperability with code
>>compiled by a C compiler, or even by the same compiler in its C mode,
>>if it has one.  The intent is to provide this capability if possible,
>>but all that extern "C" is guaranteed to do is provide C linkage.
>>
>I understand. So, please look at the following scenario:
>
>1.)  I have a very old and mean C-Library (i.e. one that is compiled
>with a C-compiler). It exposes a header file foo.h that declares a
>function f like this:
>
> void f();

Ok.  But do note that that means different things in C and C++.

>2.) Since it is a C-Library, I conclude that f can (syntactically) be
>called with arbitrary arguments. Any C-Program that includes foo.h
>should be able to do so.

Noteing you say syntactically: yes, any C program, not any C++ program.
But even at that, let's do note that you're probably
talking about the same C compiler with the same options as
the library was compiled with.

>3.) But I have a C++ program and want to use the library. Therefore I
>say
>
> extern "C"
> {
>   #include "foo.h"
> }
>
>Now I have a function  f declared and can use it. BUT NOT with
>arbitrary parameters!

Right, because void f() is void f(void) in C++.

>4.) It is also not possible to declare f myself, as for example like
>this
>
> extern "C" void f(...);
>
>because then I cannot include foo.h with all the rest of the functions
>any more. (Overloading is not possible with extern "C" - that's
>understandable)..

Right.

>So - what is the solution? I probably can introduce a cpp-file that
>does nothing but declare f like in 4.), define another function f2
>like
>
> void f2(...);
>
>that does nothing except calling f. But will the parameters be
>correctly passed? I think not necessarily, because f2 has c++ linkage
>and f has c linkage.

You want to avoid this.  Why not just prototype the function?
With some macro hackery you could get a co-ed header file going
w/o much problem.  The big deal would be finding the right types
for the argument to the functions that you have.
--
Greg Comeau                   Comeau C/C++ 4.2.44 "so close"
ONLINE COMPILER ==>           http://www.comeaucomputing.com/tryitout
4.2.45 during February!       NEW ONLINE: Try out our C99 mode!
comeau@comeaucomputing.com    http://www.comeaucomputing.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Mon, 26 Feb 2001 23:00:07 GMT
Raw View

Martin Aupperle wrote:
> se the library. Therefore I
> say
>
>         extern "C"
>         {
>           #include "foo.h"
>         }

Nobody said you can do this.  Again, extern "C" doesn't change the
language, just the linkages of the symbols.
>
> 4.) It is also not possible to declare f myself, as for example like
> this
>
>         extern "C" void f(...);
>
> because then I cannot include foo.h with all the rest of the functions
> any more. (Overloading is not possible with extern "C" - that's
> understandable)..

You're screwed.  It is not possible in general to just suck up C (be
it include files or .c files) in C++.

What you want to do is two-fold.  First, you want to fix foo.h for C
by properly indicating the arguments.   Somewhere foo.h has definite
arguments, either fixed number or type, or an explicit declaration
of variable args.  Figure out what this is and put it in the header.

Notwithstannding this, just edit foo.h and put the offending code in
an #ifdef __cplusplus

 #ifdef __cplusplus
    extern "C" void f(...);
 #else
    void f();
 #endif

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "David Thompson" <david.thompson1@worldnet.att.net>
Date: Thu, 1 Mar 2001 18:16:37 GMT
Raw View
Martin Aupperle <MikeAlpha@NoSpam_csi.com> wrote :
....
> 1.)  I have a very old and mean C-Library (i.e. one that is compiled
> with a C-compiler). It exposes a header file foo.h that declares a
> function f like this:
>
> void f();
>
> 2.) Since it is a C-Library, I conclude that f can (syntactically) be
> called with arbitrary arguments. Any C-Program that includes foo.h
> should be able to do so.
>
If it's (supposed to be) conforming to the C standard, no.
In standard C the old (K&R1) syntax return_t f( /* empty */ );
declares a function that takes *unspecified* arguments,
which are not checked by the compiler and converted only
by "access" conversions and the "default argument promotions"
(basically, char and short to int and float to double), not any
more involved conversions that would be selected by assignment
or initialization or a call to a prototyped function (which operates
as-if by assigning the arguments to the parameters).

But the actual arguments, after those conversions/promotions,
must agree with *fixed* parameters in the function definition
(body) and may not vary from one call to another, except
for certain closely related types specified by the standard
as "compatible", for example, signed int >= 0 for unsigned int.
In both standard C and C++, if you want calls with varying
argument types to the same function (not overloaded functions)
you must use a prototype declaration (required in C++ anyway)
with an ellipsis "..." , and access them (only) using the
va_* macros in <stdarg.h>/<cstdarg>.

Though not required or guaranteed by the standard, if
on your C implementation a function declared and called foo()
can successfully use va_* (after at least one fixed parameter),
then it must(?) be implementing it compatibly to (T x,...),
and so should work when used from the corresponding
C++ implementation as extern "C" return_t foo(T,...);
(Many implementations, especially register-poor x86,
just stuff all arguments on the stack in a block,
and this works, but the standards do not require it,
because it would force inefficiences on other machines.)

--
- David.Thompson 1 now at worldnet.att.net






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: MikeAlpha@NoSpam_csi.com (Martin Aupperle)
Date: Wed, 21 Feb 2001 19:51:25 GMT
Raw View
Hello,

I hope that I remember right that a function with the signature

 void f();

and compiled under a C-compiler can be called with arbitrary
arguments.
But when I declare

 extern "C" void f();

and compile under a C++ compiler, I cannot call f with arguments.

Is it correct that an empty argument list means "no arguments" even if
we compile against an implementation that allows it ( here, the
implementation of f is likely to be in a C-Module that must make no
assumptions about the arguments and therefore can be called with
arbitrary ones) ?

Thanks - Martin




------------------------------------------------
Martin Aupperle
MikeAlpha@NoSpam_csi.com
(remove NoSpam_)
------------------------------------------------

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Wed, 21 Feb 2001 21:21:42 GMT
Raw View

Martin Aupperle wrote:

> I hope that I remember right that a function with the signature
>
>         void f();
>
> and compiled under a C-compiler can be called with arbitrary
> arguments.

Yes, C is loosy goosy.  Note however that the absence of the
arguments means that certain promotions happen that wouldn't
if you had explicitly declared them.

> But when I declare
>
>         extern "C" void f();
>
> and compile under a C++ compiler, I cannot call f with arguments.

That is true.
>
> Is it correct that an empty argument list means "no arguments" even if
> we compile against an implementation that allows it ( here, the
> implementation of f is likely to be in a C-Module that must make no
> assumptions about the arguments and therefore can be called with
> arbitrary ones) ?

extern "C" doesn't change the language, just the linkage issues (how
functions get called and how the names are managed).   C++ absolutely
requires a full declaration (prototype in C terms) of the function
before it can be called (unless you're using varargs).  It's the caller
who has to support it not the definition of the function.  If you define
the function extern "C" in C++, your C modules are still free to call it
without an explicit declaration/prototype.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Jack Klein <jackklein@spamcop.net>
Date: Thu, 22 Feb 2001 19:32:10 GMT
Raw View
On Wed, 21 Feb 2001 19:51:25 GMT, MikeAlpha@NoSpam_csi.com (Martin
Aupperle) wrote in comp.std.c++:

> Hello,
>
> I hope that I remember right that a function with the signature
>
>  void f();
>
> and compiled under a C-compiler can be called with arbitrary
> arguments.
> But when I declare
>
>  extern "C" void f();
>
> and compile under a C++ compiler, I cannot call f with arguments.
>
> Is it correct that an empty argument list means "no arguments" even if
> we compile against an implementation that allows it ( here, the
> implementation of f is likely to be in a C-Module that must make no
> assumptions about the arguments and therefore can be called with
> arbitrary ones) ?
>
> Thanks - Martin

Yes, that is correct.  Defining anything with C linkage via extern "C"
does not make it C when compiled by a C++ compiler.  Only the linkage
is affected, and the standard does not actually provide a rigorous
definition of linkage, except to point out some limitations that this
imposes.

Understand that C++ does not guarantee interoperability with code
compiled by a C compiler, or even by the same compiler in its C mode,
if it has one.  The intent is to provide this capability if possible,
but all that extern "C" is guaranteed to do is provide C linkage.

--
Jack Klein
Home: http://JK-Technology.Com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]