c++ calling c functions

F

Flash Gordon

Mark McIntyre wrote, On 06/12/07 18:53:
Firstly that's true, if the function isn't declared as extern "C".
Secondly we were dicsussing C calling C++, not the other way round.
Lastly compiling the C++ routine as C doesn't count.

<snip>

Isn't it time for everyone to take this next door to comp.lang.c++ where
they know all about the compatibility between C and C++? Although they
will probably just point you at the FAQ and/or standard which tell you
how to make your C++ callable from C without compiling your C++ as C or
your C as C++.
 
I

Ian Collins

Mark said:
Firstly that's true, if the function isn't declared as extern "C".

No one disputes that.
Secondly we were dicsussing C calling C++, not the other way round.

A C++ function declared extern "C" can be called from C. Otherwise C++
code could not call C functions that have function pointers as parameters.
Lastly compiling the C++ routine as C doesn't count.

No one said it did.
Indeed, and more so between C and C++. So *in general* it isn't
possible, without invoking implementation-specific features.
Not so. Every platform I use (which excludes windows), uses a standard
C calling convention. All the C++ compilers I use use this for extern
"C" functions. Mixing C and C++ code is as trivial as mixing C and C code.
You like the word nonsense, don't you? Myself I like the word
Balderdash, its much more evocative.
Bollocks is more evocative and sums up this thread.
 
K

Keith Thompson

Mark McIntyre said:
Riight - implementation-specific magic, in other words!

The specific method used to achieve this is implementation-specific.
The specific method used to compile, link, and execute a simple C
"hello, world" program is equally implementation-specific. The
ability to call C++ from C, and to call C from C++, is specified by
the C++ standard (which is, of course, off-topic here).

If you don't believe me, check the C++ FAQ and the C++ standard.
I don't recall that, but ICBW. If so, the function in question wasn't
actually copmiled as C++ so I'm not sure it was a valid test...

``extern "C"'' is a C++-specific feature. Try compiling a source file
that contains that construct with a C compiler. You'll get a syntax
error.

The code that I said was compiled as C++ was compiled as C++. Using
``extern "C"'' doesn't make the code C; it's still C++, and in fact it
*cannot* be C unless the ``extern "C"'' is #ifdef'ed out (as it was in
my func.h header).

Go back and take a look at the output. I displayed the value
of sizeof 'a' in each function; that distinguishes (assuming
sizeof(int) > 1, which it is for the implementations I used)
between C and C++.
Correct. Try calliing a Turbo C 2 library from Watcom 32-bit C, or an
MSC 5 library from Vax C 5....

The point is that calling C from C++, or C++ from C, is no more or
less implementation-specific than calling C from C.
 
K

Keith Thompson

[ Used the wrong news server again. Sorry if you see this twice. ]
Mark McIntyre said:
Riight - implementation-specific magic, in other words!

The specific method used to achieve this is implementation-specific.
The specific method used to compile, link, and execute a simple C
"hello, world" program is equally implementation-specific. The
ability to call C++ from C, and to call C from C++, is specified by
the C++ standard (which is, of course, off-topic here).

If you don't believe me, check the C++ FAQ and the C++ standard.
I don't recall that, but ICBW. If so, the function in question wasn't
actually copmiled as C++ so I'm not sure it was a valid test...

``extern "C"'' is a C++-specific feature. Try compiling a source file
that contains that construct with a C compiler. You'll get a syntax
error.

The code that I said was compiled as C++ was compiled as C++. Using
``extern "C"'' doesn't make the code C; it's still C++, and in fact it
*cannot* be C unless the ``extern "C"'' is #ifdef'ed out (as it was in
my func.h header).

Go back and take a look at the output. I displayed the value
of sizeof 'a' in each function; that distinguishes (assuming
sizeof(int) > 1, which it is for the implementations I used)
between C and C++.
Correct. Try calliing a Turbo C 2 library from Watcom 32-bit C, or an
MSC 5 library from Vax C 5....

The point is that calling C from C++, or C++ from C, is no more or
less implementation-specific than calling C from C.
 
K

Keith Thompson

Mark McIntyre said:
Firstly that's true, if the function isn't declared as extern
"C". Secondly we were dicsussing C calling C++, not the other way
round.

We were discussing both.
Lastly compiling the C++ routine as C doesn't count.

Nobody implied that it does count. extern "C" can appear only in C++
code. Take a look at my "func.C" file; it writes output to std::cout,
so it *couldn't* be compiled as C (if you're unwilling to accept my
word that I did use a C++ compiler to compile it).
Indeed, and more so between C and C++. So *in general* it isn't
possible, without invoking implementation-specific features.

Since neither language standard specifies how to compile, link, or
execute programs, it's not possible to do *anything* without invoking
implementation-specific features.

I posted valid, portable C and C++ code that demonstrated calling a
C++ function from a C main program. My code used only features
specified by the C and/or C++ standards; the only
implementation-defined output is the result of "sizeof 'a'".
 
C

CBFalconer

Keith said:
CBFalconer said:
Keith said:
[...]

No, you can't link C++ to C, in general.

I don't believe that's correct. Further information would be
topical in comp.lang.c++, not in comp.lang.c (since it's C++, not
C, that defines the mechanisms), but see questions 32.5 and 32.6
in the "C++ FAQ Lite" at <http://www.parashift.com/c++-faq-lite/>.

The point is that C++ function names are modified, to express the
parameter types, in the linkable object code sections. C does not
do this, since it doesn't have shared function names etc. Thus the
C++ code can be told (with the "extern C {...}") that selected C
functions are to be accessed (from C++) with unmodified names. The
reverse is not possible.

Thus I gave the general method for making C object code available
to aa C++ program.

Maybe we are confusing the direction of linking? You can call C
from C++, but not C++ from C (without impossible diddling).

No, I'm asserting that it's possible to call C from C++ *and* to call
C++ from C.

The C++ FAQ agrees, and directly contradicts your claim. Its authors
certainly know C++ better than I do.

Furthermore, I've just done it. Here are my source files:

==> func.h <==
#ifdef __cplusplus
extern "C" {
#endif
void func(int i, char c, float x);
#ifdef __cplusplus
}
#endif

==> func.C <==
#include "func.h"
#include <iostream>
void func(int i, char c, float x)
{
std::cout << "In func, sizeof 'a' = " << sizeof 'a' << "\n";
std::cout << "i = " << i << ", c = '" << c << "', x = " << x << "\n";
}

Well, once more this is a matter of viewpoint, IMO. I maintain you
have declared, within a C++ program, that func.h is not a C++
routine, but a C routine, and is to be so linked. And you are then
calling C functions from a C++ program.

I believe you will find that all the standard C headers are wrapped
(internally) in the "extern C { /* whatever */ } sequence.

Note that this does NOT affect the object code in any way, only the
headers. You can't invert this and generate normal C++ modules
that can be linked into a C program. Note the "normal".
 
J

jameskuyper

Mark said:
Richard Heathfield wrote: ....

I don't recall that, but ICBW. If so, the function in question wasn't
actually copmiled as C++ so I'm not sure it was a valid test...

When you use a C++ compiler to compile a function declared with extern
"C" language linkage, the body of the function is compiled as C++
code, not as C code. Language linkage only affects the name mangling,
argument passing and how the return value is returned.
 
J

jameskuyper

CBFalconer said:
Keith Thompson wrote: ....

Well, once more this is a matter of viewpoint, IMO. I maintain you
have declared, within a C++ program, that func.h is not a C++
routine, but a C routine, and is to be so linked. And you are then
calling C functions from a C++ program.

func.h is neither a C++ routine nor a C routine. It's a header. I
presume you're referring to func() itself?
So are you actually saying that a function which can make use of
std::cout to print out the fact that sizeof 'a' == 1, even if
sizeof(int) is greater than 1, is a C function? Any feature that
distinguishes C++ from C can be used with func(). Any code which is
legal C and legal C++, but with different meanings in the two
languages, will have it's C++ meaning if found within the body of
func().

Note, in particular, that func() can call C++ functions that have NOT
been declared with "C" language linkage. Therefore, if you insist on
identifying func() as a C function, then you yourself have identified
a way for a C function to call a C++ function; something you've
claimed is impossible. The only way you can retrieve some semblance of
your original claim is to maintain that func() is neither a C function
nor a C++ function, but some brand new category.
 
B

Ben Bacarisse

CBFalconer said:
Keith said:
CBFalconer said:
Keith Thompson wrote:
[...]

No, you can't link C++ to C, in general.

I don't believe that's correct. Further information would be
topical in comp.lang.c++, not in comp.lang.c (since it's C++, not
C, that defines the mechanisms), but see questions 32.5 and 32.6
in the "C++ FAQ Lite" at <http://www.parashift.com/c++-faq-lite/>.

The point is that C++ function names are modified, to express the
parameter types, in the linkable object code sections. C does not
do this, since it doesn't have shared function names etc. Thus the
C++ code can be told (with the "extern C {...}") that selected C
functions are to be accessed (from C++) with unmodified names. The
reverse is not possible.

Thus I gave the general method for making C object code available
to aa C++ program.

Maybe we are confusing the direction of linking? You can call C
from C++, but not C++ from C (without impossible diddling).

No, I'm asserting that it's possible to call C from C++ *and* to call
C++ from C.

The C++ FAQ agrees, and directly contradicts your claim. Its authors
certainly know C++ better than I do.

Furthermore, I've just done it. Here are my source files:

==> func.h <==
#ifdef __cplusplus
extern "C" {
#endif
void func(int i, char c, float x);
#ifdef __cplusplus
}
#endif

==> func.C <==
#include "func.h"
#include <iostream>
void func(int i, char c, float x)
{
std::cout << "In func, sizeof 'a' = " << sizeof 'a' << "\n";
std::cout << "i = " << i << ", c = '" << c << "', x = " << x << "\n";
}

Well, once more this is a matter of viewpoint, IMO. I maintain you
have declared, within a C++ program, that func.h is not a C++
routine, but a C routine, and is to be so linked. And you are then
calling C functions from a C++ program.

Do you mean func rather than func.h? If you do, how can you call it a
C routine (just look at the code)? What is more, Keith Thompson (who
must be tired by now of defending this clear demonstration) took pains
to include code that shows a C++ routine (printing 1 for sizeof 'a')
being called from C (printing sizeof int for sizeof 'a').

It is C++ called from C.
 
M

Mark McIntyre

Ian said:
Not so. Every platform I use (which excludes windows), uses a standard
C calling convention. All the C++ compilers I use use this for extern
"C" functions. Mixing C and C++ code is as trivial as mixing C and C code.

I'm sure youre well aware that empirical evidence that void main() works
ok in your circumstances does not mean it is invariably or even widely
correct.
Bollocks is more evocative and sums up this thread.

Quite possibly.
 
M

Mark McIntyre

Keith said:
Nobody implied that it does count. extern "C" can appear only in C++
code. Take a look at my "func.C" file; it writes output to std::cout,
so it *couldn't* be compiled as C (if you're unwilling to accept my
word that I did use a C++ compiler to compile it).

I don't doubt you - I'm just unconvinced that this is doing what you
think it is.
I posted valid, portable C and C++ code that demonstrated calling a
C++ function from a C main program. My code used only features
specified by the C and/or C++ standards; the only
implementation-defined output is the result of "sizeof 'a'".

I agree. I'm not sure where we're disagreeing - in order to get the C++
to be callable from C, you have to make the compiler generate C code for
the function call.
 
M

Mark McIntyre

Keith said:
The
ability to call C++ from C, and to call C from C++, is specified by
the C++ standard (which is, of course, off-topic here).
If you don't believe me, check the C++ FAQ and the C++ standard.

Sure - but you have to tell the compiler to generate a non-C++ style
function. The function call has to be 100% compatible with C, you can't
use any features of C++.
[yes, I'm backtracking on my original over-bold assertion, you're
getting to me...]
``extern "C"'' is a C++-specific feature. Try compiling a source file
that contains that construct with a C compiler. You'll get a syntax
error.

You miss my point - you're telling the C++ compiler to generate C
compatible code.
The code that I said was compiled as C++ was compiled as C++. Using
``extern "C"'' doesn't make the code C; it's still C++, and in fact it
*cannot* be C unless the ``extern "C"'' is #ifdef'ed out (as it was in
my func.h header).

Go back and take a look at the output. I displayed the value
of sizeof 'a' in each function;

I understand that and didn't miss it.
The point is that calling C from C++, or C++ from C, is no more or
less implementation-specific than calling C from C.

I disagree to the extent that calling C from C is typically trivial and
doesn't require access to the original source code, whereas calling C++
from C requires the source code and some additional trickery. After all,
with suitable trickery you can call Fortran, Pascal, Python and probably
Ada from C.
 
J

jameskuyper

Mark said:
I'm sure youre well aware that empirical evidence that void main() works
ok in your circumstances does not mean it is invariably or even widely
correct.

Mixing C and C++ code is correct in the same sense that int main() is
correct; both are specified by relevant standards. The fact that many C
++ compilers actually support linking with at least one C compiler
(which is often the same compiler) is merely evidence that this
specification has not been ignored.
 
J

jameskuyper

Mark said:
Keith Thompson wrote: ....

You miss my point - you're telling the C++ compiler to generate C
compatible code.

That's true, but only in a very limited sense, and your wording does
not clearly convey what the limits on that statement are. The C++
compiler must generate code that allows the function to be called from
C, and in that sense it is compatible. But the way you say it gives
the incorrect impression that the function itself is compiled as if by
a C compiler, and therefore cannot make use of C++ features. If that's
not the impression you intended to make, you should have chosen
different wording.
 
D

Dik T. Winter

>
> You miss my point - you're telling the C++ compiler to generate C
> compatible code.

For the entry sequence only, in all other aspects it is full-fledged C++.
>
> I disagree to the extent that calling C from C is typically trivial and
> doesn't require access to the original source code, whereas calling C++
> from C requires the source code and some additional trickery. After all,
> with suitable trickery you can call Fortran, Pascal, Python and probably
> Ada from C.

Depends quite a lot on the compilers. With some it is far from trivial,
and you need specially designed interface routines to put everything in
place. The reason is that neither Fortran, nor Pascal, nor Ada state
anything about how to interface with C. But the C++ standard *does* do
it, both ways. Python states how to interface with C routines, so calling
C from Python is trivial. It is the other way here that is not trivial.

For calling Fortran from C, see for instance:
<http://www.aei.mpg.de/~jthorn/c2f.html>
which works on a limited kind of systems. And also
<http://www.vni.com/tech/imsl/8902.pdf>
which describes it for a larger number of systems, or
<http://www-zeus.desy.de/~burow/cfortran/>
for a still larger set of systems.
There is a good reason there are over 200,000 web pages that describe
how to call Fortran from C. It is far from trivial.

With Pascal the situation is a bit worse. (And there are millions of
web pages to describe it, and what I have seen of it all system
specific.) The problem is that Pascal knows nested procedures, which
C does not know about. This complicates interfacing considerably.
 
C

CBFalconer

CBFalconer wrote:
.... snip ...

func.h is neither a C++ routine nor a C routine. It's a header.
I presume you're referring to func() itself? So are you actually
saying that a function which can make use of std::cout to print
out the fact that sizeof 'a' == 1, even if sizeof(int) is greater
than 1, is a C function? Any feature that distinguishes C++ from
C can be used with func(). Any code which is legal C and legal
C++, but with different meanings in the two languages, will have
it's C++ meaning if found within the body of func().

Once you have std::cout in func.c it is no longer C source. Now
you are dealing with something else entirely. What we are worrying
about is object modules (compiled code) that can be used in C and
in C++ programs. Valid programs.

I maintain that you can't have such modules written in C++ and
callable from C. Well, maybe I should cavil a bit, and say useful
modules. But you can have useful C modules callable from C++.
 
J

James Kuyper

CBFalconer said:
Once you have std::cout in func.c it is no longer C source. Now
you are dealing with something else entirely.

Well, of course. The whole module is C++; extern "C" is a C++ feature,
not a C feature. func.c is C++ source code from beginning to end. It
describes, in C++ code, a function that must be translated in such a way
as to be callable from C, but that doesn't make it C code.

I would prefer not to repeat myself, but you didn't address my previous
comments. When you said that func.h is a C routine, what precisely did
you mean? Were you actually referring to the function func(), or did you
in fact mean the header file func.h? If you were talking about func(),
how do you reconcile that statement with your current recognition that
the body of the definition of func() contains C++ source code?
What we are worrying
about is object modules (compiled code) that can be used in C and
in C++ programs. Valid programs.
>
I maintain that you can't have such modules written in C++ and
callable from C. Well, maybe I should cavil a bit, and say useful
modules. But you can have useful C modules callable from C++.

A C++ function written to be callable from C, can, when called from C,
do anything that any other C++ function can do. In what way do such
functions fall short of being useful? Or are you denying that this is
the case? Would you care to identify any particular feature of C++ that
you believe can't be used by such a function? Keith has already
demonstrated that there are at least two C++-specific features that can
be used in such a function.

You've talked repeatedly about modules. Neither the C standard nor the
C++ standard uses that term, but the usual meaning as I understand it is
that one object code module is created by the typical compiler as a
result of translating a single translation unit. Therefore, from your
wording I get the impression that you think this is controlled at the
translation unit level. Language linkage is controlled at the function
level, not the translation unit level. A single C++ translation unit can
contain functions with "C" language linkage and functions with "C++"
language linkage (and as many other language linkages as the compiler
cares to support, such as "Fortran" or "Pascal").
 
K

Keith Thompson

CBFalconer said:
Once you have std::cout in func.c it is no longer C source. Now
you are dealing with something else entirely.

It's not "no longer" C source; it never was C source. It's C++
source, plain and simple. I never attempted to compile it with a C
compiler (if I had done so, it would have failed).
What we are worrying
about is object modules (compiled code) that can be used in C and
in C++ programs. Valid programs.

Right. In this case, the object module was generated from C++ source
by a C++ compiler.
I maintain that you can't have such modules written in C++ and
callable from C. Well, maybe I should cavil a bit, and say useful
modules.

I'm having great difficulty understanding how you can continue to make
this claim. I've clearly demonstrated how you can do *exactly* what
you claim is impossible. Perhaps the code I posted isn't useful, but
it could easily do any arbitrary thing that any C++ code could do.

You can call C++ from C.
But you can have useful C modules callable from C++.

Yes, of course.
 
K

Keith Thompson

CBFalconer said:
Well, once more this is a matter of viewpoint, IMO. I maintain you
have declared, within a C++ program, that func.h is not a C++
routine, but a C routine, and is to be so linked. And you are then
calling C functions from a C++ program.

Wrong. extern "C" is a C++ feature; it can't occur in C code.
I believe you will find that all the standard C headers are wrapped
(internally) in the "extern C { /* whatever */ } sequence.

I'm sure they are on some systems. I believe youll find that the
extern "C" {
and
}
lines are enclosed in "#ifdef __cplusplus" .. "#endif" lines.
Note that this does NOT affect the object code in any way, only the
headers. You can't invert this and generate normal C++ modules
that can be linked into a C program. Note the "normal".

What exactly do you mean by "normal"? Does the use of extern "C", a
feature defined by the C++ standard, render code abnormal?
 
K

Keith Thompson

Mark McIntyre said:
I don't doubt you - I'm just unconvinced that this is doing what you
think it is.

Perhaps I can convince you.
I agree. I'm not sure where we're disagreeing - in order to get the
C++ to be callable from C, you have to make the compiler generate C
code for the function call.

I'm not sure what you mean by that. C is a source code language. The
compiler doesn't generate "C code" for the function call; it generates
machine code. (I'm ignoring the possibility that a C++ compiler might
generate C source code as an intermediate form; that's an internal
implementation detail that's not relevant to this discussion.)

If you mean that the generated machine code for the function call
resembles the machine code that would have been generated by a C
compiler for an ordinary C-to-C function call, rather than the machine
code that would have been generated by a C++ compiler for an ordinary
C++-to-C++ function call, that may well be correct for some particular
implementation. But the question of whether something is C code or
C++ code applies *only* to source code. If you're talking about
calling conventions, that's not something that's defined by *either*
language; it's defined only by implementations, and it's not what I'm
talking about.

In this case, I wrote a function in C++ source code (and compiled it
with a C++ compiler) and called it from C source code (which I
compiled with a C compiler). The steps I took to compile the source
code and link the objects into an executable are irrelevant.

extern "C" is a C++ feature that tells the C++ compiler to generate
machine code compatible with some C compiler.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top