Topic: extern "C" and function pointer types


Author: steve@taumet.com (Steve Clamage)
Date: Sun, 19 Jul 1992 15:24:36 GMT
Raw View
raeburn@cambridge.cygnus.com (Ken Raeburn) writes:

>So then the examples on page 118 are wrong?  One of the examples there
>is very similar to the line I wrote above, and the description sounds
>very much like the function pointed to is expected to have C linkage.

The example in question:
 extern "C" typedef int (*CF)(int);
 void func(CF fp); // takes pointer to C function?
It appears that this example is not correct, in that the language
specification does not make the linkage part of the type.  (The example
is part of the commentary.)

Imagine, by way of analogy, that an implementation used different
calling sequences for static and external functions.  There is no way
to declare a pointer-to-static-function versus pointer-to-external-
function.


>Hmm.  I think I'm a little confused by the terminology.  On p.117, at
>the bottom, it says:

> Functions and objects may be declared _static_ within the {}
> of a linkage specification.  The linkage directive is ignored
> for such a function or object....

I'm confused by this too.  That paragraph was singled out for analysis
and possible re-writing at the C++ meeting this past week.

One possible interpretation for the entire mess is one proposed by
Jerry Schwarz:  In a mixed C/C++ environment, all functions must use
the same calling conventions.  By extension, other languages would
have to share the same calling conventions to be callable.  This
would allow any (non-member) function to be called via a pointer.

This restriction is actually no restriction on some systems.  On
VAX/VMS, compilers for almost all languages use the standard VAX
calling sequence.

On many systems, this restriction is not acceptable, particularly
where the machine architecture and operating system allow many
variants.  I believe that the language needs to be modified to
carry the linkage specification along with the pointer type.
--

Steve Clamage, TauMetric Corp, steve@taumet.com
Vice Chair, ANSI C++ Committee, X3J16




Author: steve@taumet.com (Steve Clamage)
Date: Fri, 10 Jul 1992 22:00:25 GMT
Raw View
raeburn@cambridge.cygnus.com (Ken Raeburn) writes:

>Something that was pointed out to me recently has been bothering me...

>On p.188 of the ARM (section 7.4), there's some discussion about
>permitting some C++ functions to use different calling sequences from
>C functions.

Right.  Calling a C function without declaring it extern "C" (or
calling a C++ function from C) might fail, apart from name mangling.

>The description seems to imply that if I want a function to have a
>local variable of pointer-to-C-function type, I must declare a global
>typedef for the type of that variable.

Not quite.  The linkage specification (extern "C") is not part of the
type, but part of the declarator (the function).  It can't be applied
to a pointer-to-function.  That is, you can't declare "pointer-to-C-
function" or "pointer-to-Pascal-function", for example, but only
"pointer-to-function".  This seems to be a hole in the language.

> extern "C" typedef void (*sig_func) (int);

This declares the pointer sig_func to have extern "C" linkage, and
says nothing about the function it points to.

> extern "C" sig_func signal (int, sig_func);

This declares function signal to have extern "C" linkage.

>Have the constraints concerning "static" specifications been relaxed,
>so I could have a C-linkage signal handler the name of which isn't
>exported from my C++ source file?

You need to use the brace-enclosed syntax:

 extern "C" {
     static int foo(int); // foo has C linkage, and is static
 }

--

Steve Clamage, TauMetric Corp, steve@taumet.com
Vice Chair, ANSI C++ Committee, X3J16




Author: raeburn@cambridge.cygnus.com (Ken Raeburn)
Date: Tue, 14 Jul 1992 02:15:17 GMT
Raw View
In article <1992Jul10.220025.24420@taumet.com> steve@taumet.com (Steve
Clamage) writes:

   raeburn@cambridge.cygnus.com (Ken Raeburn) writes:

   >On p.188 of the ARM (section 7.4), there's some discussion about

(This was a typo -- it's page 118.  Sorry.)

   >The description seems to imply that if I want a function to have a
   >local variable of pointer-to-C-function type, I must declare a global
   >typedef for the type of that variable.

   Not quite.  The linkage specification (extern "C") is not part of the
   type, but part of the declarator (the function).  It can't be applied
   to a pointer-to-function.  That is, you can't declare "pointer-to-C-
   function" or "pointer-to-Pascal-function", for example, but only
   "pointer-to-function".  This seems to be a hole in the language.

   > extern "C" typedef void (*sig_func) (int);

   This declares the pointer sig_func to have extern "C" linkage, and
   says nothing about the function it points to.

So then the examples on page 118 are wrong?  One of the examples there
is very similar to the line I wrote above, and the description sounds
very much like the function pointed to is expected to have C linkage.

   > extern "C" sig_func signal (int, sig_func);

   This declares function signal to have extern "C" linkage.

Right.  But if the typedef doesn't describe the language linkage of the
function, what does this declaration say (or what should the compiler
be assuming) about the functions pointed to by the argument and return
value?  And what if I have another function I want to declare the
"other" way -- C linkage itself, but taking a pointer to a function
with opposite language linkage from the declaration above?

   >Have the constraints concerning "static" specifications been relaxed,
   >so I could have a C-linkage signal handler the name of which isn't
   >exported from my C++ source file?

   You need to use the brace-enclosed syntax:

    extern "C" {
        static int foo(int); // foo has C linkage, and is static
    }

Hmm.  I think I'm a little confused by the terminology.  On p.117, at
the bottom, it says:

 Functions and objects may be declared _static_ within the {}
 of a linkage specification.  The linkage directive is ignored
 for such a function or object....

I'm a little unclear on what "linkage directive" refers to; couldn't
"static" be considered a linkage directive?  Anyways, I would infer
from this that in your example, either the "C" or the "static"
(probably "C", I guess) will be ignored; either way, it produces the
wrong result (assuming of course different calling conventions for the
two languages).




Author: raeburn@cambridge.cygnus.com (Ken Raeburn)
Date: Fri, 10 Jul 1992 04:38:30 GMT
Raw View
Something that was pointed out to me recently has been bothering me...

On p.188 of the ARM (section 7.4), there's some discussion about
permitting some C++ functions to use different calling sequences from
C functions.  I presume the intention is that C++ functions can
*always* use a different calling convention, if the implementor so
desires; the text describes a specific case where a non-variadic C++
function may be called more efficiently than a similar C function.

The description seems to imply that if I want a function to have a
local variable of pointer-to-C-function type, I must declare a global
typedef for the type of that variable.

My questions are:

Has this been kept in ANSI's working draft?

Is the syntax still as in the ARM -- the `extern "C"' must start off
the declaration, so you must say:
 extern "C" typedef void (*sig_func) (int);
 extern "C" sig_func signal (int, sig_func);
instead of saying something like:
 extern "C" void (*signal (int, extern "C" void (*) (int))) (int);
without requiring the extra typedef for every function type?

Has the handling of
 extern "C" {
 #include <signal.h>
 }
been examined?  Assuming a header file that doesn't handle C++ but
does do prototypes (ANSI C style), won't this result in incorrect
code?

Have the constraints concerning "static" specifications been relaxed,
so I could have a C-linkage signal handler the name of which isn't
exported from my C++ source file?

(How does this affect function name encoding?)

--- Ken