linking C++ functions in a C program

S

Stephen Sprunk

CBFalconer said:
In general, you just can't do that. C++ function names are
normally altered by the C++ compiler for various reasons. C
function names are not. So the C system can't link the C++ code.

If you mean "in general" to mean "in the normal case where extern "C" is
not used", you are correct. However, I am confident that you know C++
provides that mechanism to disable function name mangling, so your
answer is deliberately misleading. You'd have been better off simply
declaring it OT, as this entire thread has been from the beginning.

S
 
K

Keith Thompson

James Kuyper said:
If you're responding to what he wrote at that time, why don't you post
it as a response to the message in which he actually wrote it, on the
thread in which he wrote it? It's a little confusing to post it as a
response to a message I wrote, in a thread where he's said some
incorrect things about C/C++ linking, but he hasn't actually said
these particular incorrect things (at least, not yet):

James, either I'm confused or you are.

Here's the entire content of what Flash posted, excluding headers and
signature:

| CBFalconer wrote, On 06/11/08 21:54:
|
| <snip>
|
| > describes the access to the C code required. In general C++ can
| > access C code, but C cannot access C++ code.
| >
| > Remember, the languages are different.
|
| Remember, it has been pointed out to you many times and with references
| that you are WRONG. C++ defines how C code can call C++ code and you
| have been shown how it works. Since the theory says it should work and
| practice shows that it works why keep insisting that it does not?
| Neither theory nor practice are on your side.

Flash's article was a direct followup to CBFalconer's article, and
CBFalconer did write exactly the quoted incorrect words:

describes the access to the C code required. In general C++ can
access C code, but C cannot access C++ code.

Remember, the languages are different.

Did the "06/11/08" date format throw you off? It's DD/MM/YY, not
MM/DD/YY -- i.e., it's today, not 5 months ago. (MM/DD/YY is more
common in the US, DD/MM/YY in the UK; that's why I use YYYY-MM-DD
whenever possible.)
 
C

CBFalconer

Flash said:
CBFalconer wrote, On 06/11/08 21:54:



Remember, it has been pointed out to you many times and with
references that you are WRONG. C++ defines how C code can call
C++ code and you have been shown how it works. Since the theory
says it should work and practice shows that it works why keep
insisting that it does not? Neither theory nor practice are on
your side.

I sent some answers, but something has fouled, and they are not
here.
 
F

Flash Gordon

Keith Thompson wrote, On 07/11/08 02:49:
James, either I'm confused or you are.

You are not confused, James is.

Flash's article was a direct followup to CBFalconer's article, and
CBFalconer did write exactly the quoted incorrect words:

describes the access to the C code required. In general C++ can
access C code, but C cannot access C++ code.

Remember, the languages are different.

Did the "06/11/08" date format throw you off? It's DD/MM/YY, not
MM/DD/YY -- i.e., it's today, not 5 months ago. (MM/DD/YY is more
common in the US, DD/MM/YY in the UK; that's why I use YYYY-MM-DD
whenever possible.)

Yes, I should probably look at how to change it.
 
F

Flash Gordon

CBFalconer wrote, On 06/11/08 22:07:
You are quoting from, I believe, the C++ standard.

Yes he is, because that is what defines how to do it.
My point is
that C cannot call to C++ code, but C++ can call C code.

Which is EXACTLY what is wrong.
The idea
is to prepare C object code and allow the C++ system to call it
correctly, by using the extern "C" identification _in the header
file for the C code_.

1) You don't have to modify the C headers

extern "C" {
#include "c-header"
}

2) You have already been shown how to use the mechanisms defined in C++
to call C++ from C. These mechanisms to not violate the C standard any
more than any other library being callable from C does.
The C++ standard is meaningless in c.l.c. Here, we use the C std.

You can tell people that if they want to discuss it to go to
comp.lang.c++, however telling people something that is just plain WRONG
rather than redirecting people where you do not know any better is what
the trolls do. If you don't know about something, either redirect people
to an appropriate group or don't say anything.
 
P

Phil Carmody

Ian Collins said:
It does if you follow all the points. The first two are often overlooked.

Some would say it's impossible. If you are building the final
executable (main and linking) with a C++ compiler, then they
might say that you are building a C++ program that calls C
functions. However, what was required was instead a C program
which calls C++ functions. If you're careful to avoid anything
too C++-like, then C++ can be incorporated into C, but then
you're hamstrung a bit with what you can do in C++, and what's
the point. So I'd say stick C into C++, not the other way round.

Phil
 
P

Phil Carmody

Pawel Dziepak said:
7.5/3 states that: "Every implementation shall provide for linkage to
functions written in the C programming language" by allowing things like
extern "C"
7.5/6 tells us that is is possible to define function with C-style
linkage in C++ code.
7.5/9 informs us that implementation can allow to link objects from
other languages to C++ and from C++ to other languages.

Concluding, C++ standard gives possibility to link C++ functions from C
code (with some naming restrictions).

But if you're imposing restrictions, you're no longer "In general".

Phil
 
J

James Kuyper

CBFalconer said:
They are not compiled with the C++ compiler, they should be
compiled with the C compiler. ...

The purpose of the exercise was to find out how to call code compiled by
C++ from code compiled in C. How would compiling them with C serve that
purpose?
... The object code may be linked with
the C++ linker. The <extern "C"> term is only in the .h file that
describes the access to the C code required. In general C++ can
access C code, but C cannot access C++ code.

Remember, the languages are different.

Yes, they are different languages - so what?. C++ defines features that
allow C++ code to call C code, and to define C++ functions that can be
called from C.

The program below contains a function named bar() compiled by C++ with
"C" language linkage. I know from previous discussions with you that you
have said some confusing things about whether you consider such a
function to be a C function or a C++ function.

Rather than repeat my previous failed attempts to get a straight answer
out of you about that question, I've written a program that contains one
function named foo() which is compiled in C, and is therefore
unambiguously a C function. It contains another function named baz()
compiled in C++ that has "C++" language linkage, so it is unambiguously
a C++ function. foo() calls bar() which calls baz(). Therefore, no
matter how you classify bar(), this program contains a C function
calling a C++ function.

foobar.h:
========================
#ifndef FOOBAR_H
#define FOOBAR_H

#ifdef __cplusplus
extern "C" {
#endif

void foo(int);
void bar(int);

#ifdef __cplusplus
}
#endif
#endif


foo.c:
===================================
#include <stdio.h>
#include "foobar.h"

void foo(int i) {
puts("About to call bar()");
bar(i);
puts("Finished calling bar()");
}

main.C
==================================================
#include <iostream>
#include "foobar.h"

int main()
{
foo(42);
}

static void baz(int i)
{
std::cout << "the number is:" << i << std::endl;
}

void bar(int i)
{
baz(i);
}



I built the complete program as follows:

~/testprog/CfromC++(63) gcc $CFLAGS -c foo.c
In file included from foo.c:2:

~/testprog/CfromC++(64) !g++
g++ $CXXFLAGS main.C foo.o -o foobar

~/testprog/CfromC++(65) printenv CFLAGS
-std=c99 -pedantic -Wall -Wpointer-arith -Wcast-align -Wwrite-strings
-Wstrict-prototypes -Wmissing-prototypes

~/testprog/CfromC++(66) printenv CXXFLAGS
-std=c++98 -pedantic -Wall -Wpointer-arith -Wcast-align
-fno-enforce-eh-specs -ffor-scope -fno-gnu-keywords
-fno-nonansi-builtins -Wctor-dtor-privacy -Wnon-virtual-dtor
-Wold-style-cast -Woverloaded-virtual -Wsign-promo

~/testprog/CfromC++(67) foobar
About to call bar()
the number is:42
Finished calling bar()

If, as you say, C cannot access C++ code, then what exactly is the above
program doing when foo() calls bar() which calls baz()?
 
J

James Kuyper

Keith said:
James, either I'm confused or you are.

I am the one who was confused, but it's my news server's fault, not
mine. My news server got Flash's message before it got CBFalconer's
message, and my newsreader displayed Flash's message as a response to my
message.

Another part of the confusion is the notation 06/11/08. I normally use
an ISO format time: 2008-11-06. It is one of the two permitted date
format on the project where I work, but I was a fan of that format
before I ever joined this project. As a result, I misread 06/11/08 as
referring to 2006-11-08.

My message reflected irritation that wasn't caused entirely by my
misinterpretation of this one message from Flash. I knew from previous
experience that CBFalconer doesn't believe that C++ functions can be
called from C, so ever since he entered this thread I've been itching to
show him a counter-example. However, until this particular message, he
had failed to state his position in a way that made my counter-example
directly relevant. I was getting a bit frustrated waiting for him to say
something I could respond to. Then Flash's message showed up quoting
CBFalconer saying something directly relevant - I could finally post my
counter-example! However, I then noticed that the message Flash referred
to was not displayed by my newsreader, and that Flash's message referred
to a date which I misinterpreted as being from 2 years ago, so I felt a
bit disappointed.

I apologize for the confusion I passed on, and for the irritation I
expressed.
 
J

James Kuyper

CBFalconer said:
....
You are quoting from, I believe, the C++ standard. My point is
that C cannot call to C++ code, but C++ can call C code.

Yes, and that point is incorrect, as demonstrated by a response I just
posted in another branch of this discussion.
... The idea
is to prepare C object code and allow the C++ system to call it
correctly, by using the extern "C" identification _in the header
file for the C code_.

Actually, the extern "C" should only appear in the C++ code. You can put
it in C code only by using conditional compilation to ensure that it
doesn't survive translation phase 4.
The C++ standard is meaningless in c.l.c. Here, we use the C std.

Since it is the C++ standard that defines how to link C code to C++
code, this discussion should have been posted to a C++ group. However,
just because the C++ standard is off-topic here doesn't mean that it
doesn't exist, and it doesn't justify making statements here be which
would be true only if it didn't exist. The C++ standard does indeed
define how to create a function compiled in C++, the body of which can
make full use of all C++ features, but callable from C.
 
F

Flash Gordon

CBFalconer wrote, On 07/11/08 08:32:
I sent some answers, but something has fouled, and they are not
here.

The still quoted text by you above was part of one of your answers you
posted which was wrong. It was EXPLICITLY the quoted text I was refering
to where your answer was wrong but a redirection would have been
appropriate. So instead of the above quoted material you should either
have posted nothing or you should have posted a redirection. Any other
answers you might have posted are irrelevant unless they were also
erroneous and should have been redirections.
 
S

Stephen Sprunk

Phil said:
Some would say it's impossible. If you are building the final
executable (main and linking) with a C++ compiler, then they
might say that you are building a C++ program that calls C
functions. However, what was required was instead a C program
which calls C++ functions. If you're careful to avoid anything
too C++-like, then C++ can be incorporated into C, but then
you're hamstrung a bit with what you can do in C++, and what's
the point. So I'd say stick C into C++, not the other way round.

Once you have mixed C and C++ source into the same program, it is no
longer a "C program" or a "C++ program", if indeed it ever was.

It is possible to call C functions from C++ functions. It is possible
to call C++ functions from C functions. It is possible to link C and
C++ functions into the same program. All that remains for discussion is
either (a) how to accomplish it, or (b) declaring it off-topic for
comp.lang.c.

S
 
D

dj3vande

James Kuyper said:
I am the one who was confused, but it's my news server's fault, not
mine. My news server got Flash's message before it got CBFalconer's
message, and my newsreader displayed Flash's message as a response to my
message.

Blame that on the newsreader[1], not the newsswerver. Newsreaders
should be able to tell that there's an article missing, if a followup
to that article appears (and has a correct References header, which it
did on my newsserver).


An example of a sensible way to handle it:
My newsreader (trn) displays a nice ascii-art tree of the thread:
+-(1)--(1)+-(1)+-(1)--(1)+-(1)
| | | \-[1]
| | \-(1)--(1)
| \-(1)
|-(1)+-(1)+-(1)

If there's an article missing but there is a follow-up to it, the
newsreader can tell that there should be something there (from the
references header in the followups), and it will draw a hole in the
tree in the appropriate place:
+-(1)--( )+-(1)+-(1)--(1)+-(1)
^^^
If I try to go from an article to a missing parent it will tell me
"This article is not available" instead of just skipping it and going
to the next available parent.


dave

[1] The software used to read news, not (at least in this case) the
person reading news.
 
I

Ian Collins

James said:
I am the one who was confused, but it's my news server's fault, not
mine. My news server got Flash's message before it got CBFalconer's
message, and my newsreader displayed Flash's message as a response to my
message.
You weren't the only one. Something went wrong somewhere yesterday.
 
C

CBFalconer

James said:
CBFalconer wrote: Various incorrect things.
.... snip ...

Rather than repeat my previous failed attempts to get a straight
answer out of you about that question, I've written a program that
contains one function named foo() which is compiled in C, and is
therefore unambiguously a C function. It contains another function
named baz() compiled in C++ that has "C++" language linkage, so it
is unambiguously a C++ function. foo() calls bar() which calls
baz(). Therefore, no matter how you classify bar(), this program
contains a C function calling a C++ function.

foobar.h:
========================
#ifndef FOOBAR_H
#define FOOBAR_H

#ifdef __cplusplus
extern "C" {
#endif

void foo(int);
void bar(int);

#ifdef __cplusplus
}
#endif
#endif

foo.c:
===================================
#include <stdio.h>
#include "foobar.h"

void foo(int i) {
puts("About to call bar()");
bar(i);
puts("Finished calling bar()");
}

main.C
==================================================
#include <iostream>
#include "foobar.h"

int main() {
foo(42);
}

static void baz(int i) {
std::cout << "the number is:" << i << std::endl;
}

void bar(int i) {
baz(i);
}

I concede my posts have not been accurate. I still don't think C
calling C++ is convenient, accurate, and really useful, although
possible. In the above:

foobar.h sets up definitions of foo and bar that requires them to
be called without name adornment The actual code is implemented in
the C++ file (.cpp would be more descriptive than .C, IMO). I
guess the compiler can generate two references to foo, one adorned,
and one not adorned, although that is an unnecessary complication.

Some confusion: Note that the code for bar is compiled with a C++
compiler. Thus it must follow C++ rules, for such things as
reserved names, size of char constants, etc. It can thus make a
great difference if bar is moved to a .c file, #includes
"foobar.h", and totally removed from main.C. To me, this is a
cleaner organization, and ensures that C code is compiled as C, and
C++ code is compiled as C++. Conceded, it will prevent using
std::cout etc.

I think I have avoided confusing my biases with facts here :)
 
J

jameskuyper

CBFalconer wrote:
....
I concede my posts have not been accurate. I still don't think C
calling C++ is convenient, accurate, and really useful, although
possible. In the above:

foobar.h sets up definitions of foo and bar that requires them to
be called without name adornment The actual code is implemented in
the C++ file (.cpp would be more descriptive than .C, IMO). ...

? - The actual code for foo() is in the C file.
... I
guess the compiler can generate two references to foo, one adorned,
and one not adorned, although that is an unnecessary complication.

I know of no way to tell the either compiler to do so, nor any reason
to want to. Both functions are callable without adornment from
anywhere that their declarations from foobar.h are in scope.
Some confusion: Note that the code for bar is compiled with a C++
compiler. Thus it must follow C++ rules, for such things as
reserved names, size of char constants, etc. It can thus make a
great difference if bar is moved to a .c file, #includes
"foobar.h", and totally removed from main.C.

Well, the whole purpose of bar() is to be callable from C code, while
having access to C++ functionality. It would lose that access if were
moved to the .c file. It's sort of like saying: that bridge would be
much less likely to fall in the river if you moved it over onto the
west bank. The point of the bridge is to cross that river, and the
point of bar() is to enable communication between the C and C++ parts
of the program.
... To me, this is a
cleaner organization, and ensures that C code is compiled as C, and
C++ code is compiled as C++. Conceded, it will prevent using
std::cout etc.

Yes, thereby defeating the whole purpose of the code. This is just a
simplified example, a more realistic example would involve linking
together two different libraries, one written in C, one written in C+
+, and making use of both libraries from within a single program.
Clearly, either library could be rewritten in the other language;
neither language has unique capabilities, just some things that it
does better than the other - but why re-write when C++ provides the
tools needed to link them together without a rewrite?
 
I

Ian Collins

CBFalconer said:
I concede my posts have not been accurate. I still don't think C
calling C++ is convenient, accurate, and really useful, although
possible. In the above:
Accurate?

My most common use for C calling C++ is C++ device drivers. The
interface between the operating system and drivers is a often a struct
of function pointers. I use extern "C" linkage functions as the public
interface for my drivers to populate these tables.

Calls between languages don't have to be direct. For a driver writer,
calling through function pointers is both convenient and really useful.
 
S

Stephen Sprunk

CBFalconer said:
I concede my posts have not been accurate. I still don't think C
calling C++ is convenient, accurate, and really useful, although
possible. In the above:

It's sometimes inconvenient, since you lose certain benefits of C++ and
have to add some extra syntactic sugar when you make a function callable
from C. However, it is quite certainly "accurate" and "useful".

I've worked with several libraries that used C++ internally and provided
both a C interface and a C++ interface; the C interface was simply a
bunch of wrapper functions that manipulated the C++ interface, which a C
program couldn't see (because it used classes).
foobar.h sets up definitions of foo and bar that requires them to
be called without name adornment The actual code is implemented in
the C++ file (.cpp would be more descriptive than .C, IMO).

..cpp or .cc is the usual convention when there's any possibility of
confusion. The .C convention doesn't work on systems that aren't
case-sensitive (e.g. Windows).
I guess the compiler can generate two references to foo, one adorned,
and one not adorned, although that is an unnecessary complication.

That's not required.

The C compiler processing foo.c will see a normal C function named
foo(), and it will generate the object code as it always does.

The C++ compiler processing main.C will see an extern "C" function named
foo(), and any time that C++ code calls it, it will call the unmangled C
name instead of the default mangled C++ name.

Since the C++ code is calling the unmangled name foo(), and the C
compiler produced a function named foo(), everything works.
Some confusion: Note that the code for bar is compiled with a C++
compiler. Thus it must follow C++ rules, for such things as
reserved names, size of char constants, etc. It can thus make a
great difference if bar is moved to a .c file, #includes
"foobar.h", and totally removed from main.C. To me, this is a
cleaner organization, and ensures that C code is compiled as C, and
C++ code is compiled as C++. Conceded, it will prevent using
std::cout etc.

bar() and baz() are both C++ functions, and are properly compiled with a
C++ compiler. bar() is callable from C, due to the way it's declared,
but baz() is not. However, bar() can call baz(), which makes bar() a
"wrapper" function for baz().

The wrapper is unnecessary in this case (baz() could have been extern
"C" and called directly from foo(), since its declaration doesn't
require any special C++ features), but it's a useful technique at times.

S
 
J

James Kuyper

Stephen Sprunk wrote:
....
bar() and baz() are both C++ functions, and are properly compiled with a
C++ compiler. bar() is callable from C, due to the way it's declared,
but baz() is not. However, bar() can call baz(), which makes bar() a
"wrapper" function for baz().

The wrapper is unnecessary in this case (baz() could have been extern
"C" and called directly from foo(), since its declaration doesn't
require any special C++ features), but it's a useful technique at times.

In a more complicated version I've been thinking of, just to demonstrate
what's possible using this approach, the equivalent of baz() would be a
C++ function that uses many C++-specific features as part of the
function interface (it's a templated operator() overload with a default
argument that is a class member function), making it impossible to
declare it as extern "C".

The point is that the function interface (return type and parameter
list) of bar() can only use features that are shared between C and C++,
but the body of bar() has no such restrictions, and can include calls to
functions that are not subject to that same restriction.
 

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

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top