c++ calling c functions

K

Keith Thompson

Dik T. Winter said:
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.
[...]

Actually, Ada does specify how to interface with C, in considerable
detail.
 
I

Ian Collins

CBFalconer said:
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++.
Rubbish, you can provide an extern "C" prototype interface to any C++
module. I have written device drivers (which are loadable kernel
modules) in C++.
 
C

CBFalconer

Keith said:
.... snip ...


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

I think we are getting at the heart of the disagreement. To me, a
normal C++ 'module' contains such things as functions with modified
names, reflecting the parameters, and used to separate the various
forms. The code has not been modified by an "extern C" clause. It
is usable without special care in any C++ program. (There is some
speculation here, because I don't really use C++).

To call that system from a C module, something has to supply the
modified function name. There is no such provision in C. It is
hard to add controlled gubris to a function name. Therefore you
can't call the C++ code from C.

However, you can call a C module from C++. All you have to do is
wrap the .h file in the "extern C {}" magic, and the prototype
names will be used unchanged. It is much easier to forbid name
modification than to insist on it, and specify the actual
modifications. Note that the C compilation is not affected because
that magic is guarded by "if __cplusplus", and the C standard
forbids any C implementation from defining __cplusplus.
 
C

Chris Torek

I think we are getting at the heart of the disagreement. To me, a
normal C++ 'module' contains such things as functions with modified
names, reflecting the parameters, and used to separate the various
forms.

The thing is, you can tell *every* [%] C++ compiler *not* to use "mangled
names", simply by writing one special C++ declaration in front of
the function definition.

[% See parenthetical caveat below, also marked with [%].]

Imagine, if you will, that we have -- instead of C and C++ -- the
two languages P and L. In P, we write:

linkage "L":
declare foo as function taking integer and returning nothing.
begin function foo:
input parameter x is integer;
write x;
end function foo.
end linkage "L".

declare bar as function taking Lstring and returning nothing.
begin function bar:
input parameter p is Lstring;
write p;
end function bar.

In L, however, we write:

extern func foo [int];
extern (interface "P") func bar [string];

Now a program in language L can call both foo and bar, even though
both are defined in language P. A program in language P can also
(of course) call both foo and bar. Here, both languages have some
sort of special syntax specifically designed to interface with each
other.

If P and L use header files, then -- since the syntax differs --
we must obviously write two *separate* header files for P and L
to declare foo and bar in each. (The indented text above *is*
the L-language header, in fact. The P-language header simly
omits the source code for foo and bar -- the parts from "begin
function" to "end function".)

In the case of C and C++, however, instead of *both* languages
having some sort of special syntax, only C++ has the special syntax.
Luckily, only one such syntax is required -- normally, to turn off
the "name mangling" you know about. ([%] On some systems it might
do more and/or less than just disable name mangling. In particular,
C compilers are *also* allowed to do name mangling; it is just that
most avoid it, both because of tradition/history, and because extra
work is then required to handle old K&R-style non-prototyped
functions. The key item, in any case, is that the C++ special
syntax, required in every C++ compiler, tells that C++ compiler
that the functions so declared should be compiled such that they
use the C++ implementation's C-language linkage conventions, whatever
those are. That allows any later definition of those functions --
in any language, even if they are written in Pascal or Java -- to
call or be called from anything that is capable of using those
C-language linkage conventions.)

Because only the C++ side has the special syntax, you have to prefix
any C++ function *definition* with the appropriate syntax, so that
the C++ compiler does whatever is required to make that C++ function
callable from C.

At the same time, though, because C and C++ share so much syntax,
we can actually write a single "foo.h" header file, using those
annoying "#ifdef __cplusplus" lines, so that our two logically-separate
headers (for-c-foo.h and for-c++-foo.h) occupy a single source
file. We could do the same with the P and L headers, if there is
some sort of shared preprocessor for each, but there is less reason
to do so, since we would end up with:

#ifdef __P_LANGUAGE__

linkage "L":
declare foo as function taking integer and returning nothing.
end linkage "L".

#else

extern func foo [int];

#endif

If C were to adopt the C++ syntax for "extern", we could even
eliminate the annoying #ifdef from the shared C and C++ headers.
Perhaps we could also add name-mangling to C compilers so that we
could write:

extern "C++" somefunc(const char *);

instead of using:

extern "C" somefunc(const char *p) { ... }

on the C++ side -- but that would just be "completing the symmetry",
not actually adding any new functionality.
 
J

jameskuyper

CBFalconer wrote:
....
I think we are getting at the heart of the disagreement. To me, a
normal C++ 'module' contains such things as functions with modified
names, reflecting the parameters, and used to separate the various
forms. The code has not been modified by an "extern C" clause. It
is usable without special care in any C++ program. (There is some
speculation here, because I don't really use C++).

To call that system from a C module, something has to supply the
modified function name. There is no such provision in C. It is
hard to add controlled gubris to a function name. Therefore you
can't call the C++ code from C.

As I've said before, language linkage is controllable at the function
level, not the module level. A C++ translation unit containing the
definition of a function with "C" language linkage can also contain
other functions declared with "C++" language linkage. So - is that a C
module or a C++ module? If it's a C++ module, is it a "normal" one?
The functions with "C" language linkage can be called by name from
both C code and C++ code, without any need to worry about name
mangling. Are those functions C functions or C++ functions? The only
"special care" needed in C++ code is to make sure that the declaration
of a function with "C" language linkage must actually say so. I don't
consider that "special care". It's the same issue as, and no more
difficult than, giving the correct return type in a function
declaration.
 
K

Keith Thompson

CBFalconer said:
I think we are getting at the heart of the disagreement. To me, a
normal C++ 'module' contains such things as functions with modified
names, reflecting the parameters, and used to separate the various
forms. The code has not been modified by an "extern C" clause. It
is usable without special care in any C++ program. (There is some
speculation here, because I don't really use C++).

I think the problem is that you're associating "C++" with an object
code module. C++ is a source code language. The contents of an
object module generated by a C++ compiler from a C++ source file are
entirely implementation-specific. The mangled names are not part of
C++; they're something used by the implementation, largely invisible
to portable C++ code.

And once again, extern "C" is a C++ feature. It's specified by the
C++ standard, and there is absolutely nothing "abnormal" or non-C++
about it.

A C++ source file containing an extern "C" directive is 100% pure C++.
To call that system from a C module, something has to supply the
modified function name. There is no such provision in C. It is
hard to add controlled gubris to a function name. Therefore you
can't call the C++ code from C.

Then please explain how I'm able to do exactly that. You can do so
only by assigning nonsensical meanings to the phrases "C code" and
"C++ code".

[...]
 
C

CBFalconer

Keith said:
.... snip ...

A C++ source file containing an extern "C" directive is 100% pure C++.


Then please explain how I'm able to do exactly that. You can do so
only by assigning nonsensical meanings to the phrases "C code" and
"C++ code".

In other words you are wrapping the _entire_ C++ source module with
the 'extern "C" {}' wrapper. That means you need to create a
separate .h header file, with the same wrapper, for use only in the
C linkage (This is hazy). It also means that there is no header
file for C++ use (unless you create another one).

The module that you compiled with the C++ compiler is not usable in
a C++ program without the extra effort of the separate header
file. To me this is not what is desired.

I will retract the 'impossible' claim, and replace it with
'impracticable'.
 
K

Keith Thompson

CBFalconer said:
In other words you are wrapping the _entire_ C++ source module with
the 'extern "C" {}' wrapper. That means you need to create a
separate .h header file, with the same wrapper, for use only in the
C linkage (This is hazy). It also means that there is no header
file for C++ use (unless you create another one).

No, the 'extern "C" {}' wrapper is *part of* the C++ source module.

I wrote a single header file, func.h, in which the 'extern "C" {' and
'}' lines were wrapped in "ifdef __cplusplus" ... "#endif". This is
*extremely* common practice.
The module that you compiled with the C++ compiler is not usable in
a C++ program without the extra effort of the separate header
file. To me this is not what is desired.

Only a single header file is needed. That single header file need to
be written to be compatible with both C and C++, which is not at all
difficult. Take a look at what I posted.
I will retract the 'impossible' claim, and replace it with
'impracticable'.

And you're still utterly wrong.

I. Showed. You. How. To. Do. It.

But since this is off-topic for comp.lang.c, I'm going to drop this.
If you're curious about this, post to comp.lang.c++ (but first read
the C++ FAQ and/or any decent book on C++).
 
J

James Kuyper

CBFalconer said:
In other words you are wrapping the _entire_ C++ source module with
the 'extern "C" {}' wrapper. That means you need to create a
separate .h header file, with the same wrapper, for use only in the
C linkage (This is hazy). It also means that there is no header
file for C++ use (unless you create another one).

The language linkage specification can be used in several different ways:

extern "Pascal" double pfunc(int);

typedef extern "C" char *cstringfunc(char*, const char*);

extern "Fortran" {
// Identifiers between the curly brackets all have "Fortran"
// Language Linkage
}

The last one makes it trivial to mark large blocks of code as having a
particular language linkage. And it's also quite trivial to create a
single same header usable equally well in both C and in C++ to describe
functions with "C" language linkage:

common_header.h:
#ifdef __cplusplus
extern "C" {
#endif
// Normal C header file contents
#ifdef __cplusplus
}
#endif

To summarize: you do not need to wrap an entire C++ source module in
this fashion, unless you want to; it's perfectly feasible to apply it to
only a small portion of the module, or even a single function. You do
not need separate header files for C and C++.
The module that you compiled with the C++ compiler is not usable in
a C++ program without the extra effort of the separate header
file. To me this is not what is desired.

I will retract the 'impossible' claim, and replace it with
'impracticable'.

The apparent impracticality of this is largely due to your own
unfamiliarity with how it's done. It's not very difficult to use; it
requires the addition of only six extra lines to a typical header file.

The trickiest part is figuring out what you want to do once you've
pierced the C/C++ boundary; and that's not tricky because it's hard to
do. It's tricky because there's such a wide variety of options to consider.
 
C

CBFalconer

Chris said:
CBFalconer said:
I think we are getting at the heart of the disagreement. To me, a
normal C++ 'module' contains such things as functions with modified
names, reflecting the parameters, and used to separate the various
forms.

The thing is, you can tell *every* [%] C++ compiler *not* to use "mangled
names", simply by writing one special C++ declaration in front of
the function definition.

[% See parenthetical caveat below, also marked with [%].]

Imagine, if you will, that we have -- instead of C and C++ -- the
two languages P and L. In P, we write:
.... snip ...

I have put this aside for further study, along with Keiths separate
example. I think we are defining interconnection differently, but
am not sure now.

I am talking about complete modules, taking advantages of all the
abilities of their respective language, being used in object form
in the other language.
 
I

Ian Collins

CBFalconer said:
Chris said:
CBFalconer said:
Keith Thompson wrote:

What exactly do you mean by "normal"? Does the use of extern "C",
a feature defined by the C++ standard, render code abnormal?
I think we are getting at the heart of the disagreement. To me, a
normal C++ 'module' contains such things as functions with modified
names, reflecting the parameters, and used to separate the various
forms.
The thing is, you can tell *every* [%] C++ compiler *not* to use "mangled
names", simply by writing one special C++ declaration in front of
the function definition.

[% See parenthetical caveat below, also marked with [%].]

Imagine, if you will, that we have -- instead of C and C++ -- the
two languages P and L. In P, we write:
.... snip ...

I have put this aside for further study, along with Keiths separate
example. I think we are defining interconnection differently, but
am not sure now.

I am talking about complete modules, taking advantages of all the
abilities of their respective language, being used in object form
in the other language.
So are we. It does work, honest! I produce a lot of mixed C and C++
applications and from a C++ perspective, there are only a couple of
restrictions imposed on functions declared extern "C".

Due to C not having function overloading, extern "C" functions can't be
overloaded by other extern "C" functions.

You can't declare a function template as extern "C".

Other than those, and C++ function with extern "C" linkage is exactly
that, a C++ free function with an alternative linkage specification.
There aren't any restrictions on what the function does, or calls.
 
T

teju

This is where this 'goes wrong' I think...


I don't think so. The C++ compiler would have turned func into something
like func::func@as:33:22 or some such other decorated nonsense. TheC
compiler would have generated a call to _func or whatever. The linker
can't resolve this.
The only way the modules will link is if main.lowercase-cwas compiled
as C++ /OR/ if some implementation-specific magic went on to tell the
linker to look for multiple possible versions of the name.


Indeed - so _in general_ this isn't possible, as CBF said in the first
place?

with extern "c" much worked and after making some changes now both
projects merged and working fine but now i need to access c++ object
from my c code...

now how can i do this?
 
I

Ian Collins

teju said:
with extern "c" much worked and after making some changes now both
projects merged and working fine but now i need to access c++ object
from my c code...

now how can i do this?

Please, don't rake this thread up again, it has just died down. Read
this thread (and the countless others here and down the hall in c.l.c++).
 
B

Bill Reid

Another old one...this one really illustrates one of the REAL
problems here...a LOT of the most frequent posters couldn't
program a computer to save their lives, but they sure know
how to jabber endlessly debating about cut-and-dried technical
details of programming languages...

CBFalconer said:
In other words you are wrapping the _entire_ C++ source module with
the 'extern "C" {}' wrapper. That means you need to create a
separate .h header file, with the same wrapper, for use only in the
C linkage (This is hazy). It also means that there is no header
file for C++ use (unless you create another one).

The module that you compiled with the C++ compiler is not usable in
a C++ program without the extra effort of the separate header
file. To me this is not what is desired.

I will retract the 'impossible' claim, and replace it with
'impracticable'.

You were informed by me several billion posts ago in plain English
in this thread exactly how to do it. This was about the third time I've
posted this fairly simple information. You've been informed by several
others that they do it routinely. I do it routinely. You've been shown
simple example code illustrating exactly how to do it. You've been
pointed to a very well-written explanation how to do it in the C++
FAQ. You've had the all the technical considerations involved
described to you in atomic detail.

But you're still arguing about it. Therefore, I can only come to
one conclusion: you're a useless moron.

As far as practicality is concerned, there really aren't that many
good C libraries to perform modern non-trivial computing tasks these
days. So I just go ahead and use C++ libraries, called from my
C code. I also much prefer C++ for certain types of work (particularly
some types of simulations), and I like to be able to mix and match
some other modules I've written in C with these C++ modules.

And of course, my language mixing doesn't just end with C++
and C, but then again, as I've always said, I like to get things
done...but that's not the "charter" here, is it? You've got your
own "special" talents that you so unashamedly share with everybody
here...and what a wonderful world, you've found a "home" with
others of similar intellect...
 

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,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top