extern "C" linker error ---- please explain

  • Thread starter Generic Usenet Account
  • Start date
G

Generic Usenet Account

Our C++ program was linked with some legacy C functions. We had used
the extern "C" declaration, and everything was working fine. Then
someone thought that it would be better to have a consistent file
naming convention and renamed the files with the legacy C functions
from .c to .cxx. Lo and behold we started getting linker errors left
and right. When we reverted back to the old naming convention, the
problem went away. Also, the problem did not manifest when we kept the
..cxx name and replaced extern "C" with simply extern.

Any help explaining this phenomenon will be appreciated.

Thanks,
Gus
 
V

Victor Bazarov

Generic said:
Our C++ program was linked with some legacy C functions. We had used
the extern "C" declaration, and everything was working fine. Then
someone thought that it would be better to have a consistent file
naming convention and renamed the files with the legacy C functions
from .c to .cxx. Lo and behold we started getting linker errors left
and right. When we reverted back to the old naming convention, the
problem went away. Also, the problem did not manifest when we kept the
.cxx name and replaced extern "C" with simply extern.

Any help explaining this phenomenon will be appreciated.

It could be that your function definitions did not have 'extern "C" ' in
them. IOW, you _declared_ the functions as if they were "C", and then
defined them (in your .cxx files) as "C++". Those translation units that
included the headers needed the functions with the "C" linkage, and there
were none (since the function definitions were "C++").

IOW, you were supposed to have both:
---------------------------------------------- foo.h
extern "C" {
int foo();
double bar();
}
---------------------------------------------- foo.cxx
extern "C" {

int foo()
{
return 42;
}

double bar()
{
return 3.14;
}

} /* extern "C" */
 
L

Larry I Smith

Generic said:
Our C++ program was linked with some legacy C functions. We had used
the extern "C" declaration, and everything was working fine. Then
someone thought that it would be better to have a consistent file
naming convention and renamed the files with the legacy C functions
from .c to .cxx. Lo and behold we started getting linker errors left
and right. When we reverted back to the old naming convention, the
problem went away. Also, the problem did not manifest when we kept the
.cxx name and replaced extern "C" with simply extern.

Any help explaining this phenomenon will be appreciated.

Thanks,
Gus

What compiler are you using?
Some compilers use the filename extension to determine
whether to compile the code as C or C++. The 'cxx'
filename extension is usually interpreted as C++ code.

If you use a 'make' program to build your system, then
either the rules in your Makefile or the DEFAULT rules
built in to the 'make' program that you are using may
be forcing files with a 'cxx' extension to be compiled
as C++ code (even when they contain C code).

In general, C files should have a '.c' filename extension.
Otherwise some compilers and 'make' programs can get very
confused.

Regards,
Larry
 
M

Mike Smith

Generic said:
Our C++ program was linked with some legacy C functions. We had used
the extern "C" declaration, and everything was working fine. Then
someone thought that it would be better to have a consistent file
naming convention and renamed the files with the legacy C functions
from .c to .cxx. Lo and behold we started getting linker errors left
and right. When we reverted back to the old naming convention, the
problem went away. Also, the problem did not manifest when we kept the
.cxx name and replaced extern "C" with simply extern.

Your compiler probably assumes that extensions like .cxx, .cpp, etc. are
C++ and compiles them as C++ instead of C.
 
G

Generic Usenet Account

Mike said:
Your compiler probably assumes that extensions like .cxx, .cpp, etc. are
C++ and compiles them as C++ instead of C.

Okay, here's a follow up question. What does it mean to compile C code
as C++ instead of C? Isn't the intent of the compilation process to
convert source code into object code? Is there a difference between
the object code that is generated when compiling C code as C versus
compiling the same code as C++?

Gus
 
L

Larry I Smith

Generic said:
Okay, here's a follow up question. What does it mean to compile C code
as C++ instead of C? Isn't the intent of the compilation process to
convert source code into object code? Is there a difference between
the object code that is generated when compiling C code as C versus
compiling the same code as C++?

Gus

It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++. The link
libs req'd may (usually do) differ. The function naming convention
(inside the compiled object files and libs) differs; a function
foo(int) will have one name in the object (.o) file when compiled
as C code, but a very different name in the object file when
compiled as C++ code (the 'mangled' C++ name contains encoded info
about the function's args, but the C name does not, and the C name
will usually start with an underscore (e.g. _foo)).

If the code is meant to be C, then compile it as C.
If you're using the GNU GCC compiler set, then compile/link
C code using 'gcc' and compile/link C++ code using 'g++'.
Here are some simple examples that might be found in a Makefile:

// compile/link a simple C prog named 'a'
gcc -o a a.c

// compile C source to object files a1.o, a2.o, & a3.o
gcc -c a1.c
gcc -c a2.c
gcc -c a3.c
-or-
gcc -c a1.c a2.c a3.c

// link C object files and some libs to create
// a program named 'cprog'
gcc -o cprog a1.o a2.o a3.o -lsomelib -lanotherlib

// compile/link simple C++ progs named 'b', 'c', and 'd'
g++ -o b b.cc
g++ -o c c.cxx
g++ -o d d.cpp

// compile C++ source to object files e1.o, e2.o, & e3.o
g++ -c e1.cxx
g++ -c e2.cxx
g++ -c e3.cxx
-or-
g++ -c e1.cxx e2.cxx e3.cxx

// link C++ object files and some libs to create
// a program named 'cppprog'
g++ -o cppprog e1.o e2.o e3.o -lsomelib -lanotherlib


When using gcc/g++ use the correct one (gcc or g++) to
link your code - as shown in the above examples (rather
than calling 'ld' directly).
gcc and g++ (especially g++) pass additional info to
the linker that is language specific.

Regards,
Larry
 
C

Clark S. Cox III

It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.
Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?
 
L

Larry I Smith

Victor said:
Larry said:
[...] For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.
REALLY?!

[..].

My info may be out of date, but C pushes the args
in left-to-right order (allowing support for a variable
number of args), and C++ uses the Pascal-style
of right-to-left order. The order of the args on the
stack is (was in the 80's) standardized to allow libs
from multiple vendors to inter-operate.

As I recall, in C the calling code cleans up the call stack
after a function call returns, but in C++ the called
function cleans up the call stack before returning.

Regards,
Larry
 
V

Victor Bazarov

Larry said:
Victor said:
Larry said:
[...] For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.
REALLY?!


[..].


My info may be out of date, but C pushes the args
in left-to-right order (allowing support for a variable
number of args), and C++ uses the Pascal-style
of right-to-left order.

So, this suggests that C++ has no support for a variable number of rags.
Is that so?
The order of the args on the
stack is (was in the 80's) standardized to allow libs
from multiple vendors to inter-operate.

As I recall, in C the calling code cleans up the call stack
after a function call returns, but in C++ the called
function cleans up the call stack before returning.

I think you've confused C++ with Pascal.

V
 
L

Larry I Smith

Larry said:
Victor said:
Larry said:
[...] For one thing the args to function calls are
pushed on to the stack in different order in C vs C++. REALLY?!

[..].

My info may be out of date, but C pushes the args
in left-to-right order (allowing support for a variable
number of args), and C++ uses the Pascal-style
of right-to-left order. The order of the args on the
stack is (was in the 80's) standardized to allow libs
from multiple vendors to inter-operate.

As I recall, in C the calling code cleans up the call stack
after a function call returns, but in C++ the called
function cleans up the call stack before returning.

Regards,
Larry

Oops, the stack order pushes I mention above are reversed.

In C the caller cleans up the stack because a variable
number of args may have been pushed, and the called function
may not know how much stack to pop.

It's tough getting old - the memory goes first...

Larry
 
L

Larry I Smith

Victor said:
Larry said:
Victor said:
Larry I Smith wrote:

[...] For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.

REALLY?!


[..].


My info may be out of date, but C pushes the args
in left-to-right order (allowing support for a variable
number of args), and C++ uses the Pascal-style
of right-to-left order.

So, this suggests that C++ has no support for a variable number of rags.
Is that so?
The order of the args on the
stack is (was in the 80's) standardized to allow libs
from multiple vendors to inter-operate.

As I recall, in C the calling code cleans up the call stack
after a function call returns, but in C++ the called
function cleans up the call stack before returning.

I think you've confused C++ with Pascal.

V

A long time ago in a galaxy far, far away, my job was to write
asm code to interface with both C and C++.

Page 3 in the following doc provides a brief summary of the
call stack procedures:

http://www.nuvisionmiami.com/books/asm/articles/CppCalls.pdf

The example asm module discussed uses the C calling convention
(push args in reverse order, caller cleans up the stack after
the called function returns). Note that the functions discussed
are all declared 'extern "C"' in the C++ code to advise the
compiler that these functions use the C call stack layout
rather than the C++ call stack layout.

Following is another doc describing the differences between the
C and C++ call stack layouts. Although this doc is MS VC specific,
variations of the '__cdecl' and 'thiscall' stack layouts are
used on most OS'es. The '__cdecl' style stack is used for C
functions and C++ functions with variable arg list, and the
'thiscall' style stack is used for C++ functions that do not
have a variable arg list.

http://www.codeproject.com/cpp/calling_conventions_demystified.asp

Regards,
Larry
 
L

Larry I Smith

Clark said:
Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?

See my 2 replies to Victor for the details.

Regards,
Larry
 
V

Victor Bazarov

Larry said:
Clark said:
[...]
It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.

Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?


See my 2 replies to Victor for the details.

I pains me to see your common sense go along with your memory...
 
L

Larry I Smith

Victor said:
Larry said:
Clark said:
On 2005-06-09 15:34:28 -0400, Larry I Smith <[email protected]>
said:

[...]
It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.


Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?


See my 2 replies to Victor for the details.

I pains me to see your common sense go along with your memory...

Huh? Did you read the docs I ref'd in my last reply to you
(the one posted AFTER the 'memory' comment)?

Regards,
Larry
 
V

Victor Bazarov

Larry said:
Victor said:
Larry said:
Clark S. Cox III wrote:


On 2005-06-09 15:34:28 -0400, Larry I Smith <[email protected]>
said:


[...]
It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.


Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?




See my 2 replies to Victor for the details.

I pains me to see your common sense go along with your memory...


Huh? Did you read the docs I ref'd in my last reply to you
(the one posted AFTER the 'memory' comment)?

Of course I did. Did you? Do it again. Read the top half of the page 3
and tell me where does it say that the order of arguments for a C++
function call is _reverse_ compared to a C function call.

Once you've done that, explain what your reply to me has to do with the
C++ _standard_language_, which makes no claim WHATSOEVER how (in what
order and where) arguments are passed to the function.

V
 
H

Howard

Larry I Smith said:
Victor said:
Larry said:
Clark S. Cox III wrote:

On 2005-06-09 15:34:28 -0400, Larry I Smith <[email protected]>
said:

[...]
It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.


Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?




See my 2 replies to Victor for the details.

I pains me to see your common sense go along with your memory...

Huh? Did you read the docs I ref'd in my last reply to you
(the one posted AFTER the 'memory' comment)?

Regards,
Larry

The codeproject site doesn't seem to be responding.

But regardless of what that doc might say, it's neither the C nor the C++
standard. The standards documents specify the actual requirements of the
languages. If you find anything in the standards that specifies such
conventions, please let us know. Otherwise, there is no such requirement,
and compiler implementors are free to implement function calls as they
please (given the constraints of the platform they're targeting, obviously).

-Howard
 
M

Mike Smith

Larry said:
Victor said:
Larry said:
Clark S. Cox III wrote:

On 2005-06-09 15:34:28 -0400, Larry I Smith <[email protected]>
said:

[...]
It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.

Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?

See my 2 replies to Victor for the details.

I pains me to see your common sense go along with your memory...

Huh? Did you read the docs I ref'd in my last reply to you
(the one posted AFTER the 'memory' comment)?

That may have been the way it was in the *particular implementations*
that you worked on, but is not defined by the standard. In fact, if I
recall correctly, the C++ standard does not even require that there *be*
a stack at all, as long as the arguments get passed to the function somehow.
 
L

Larry I Smith

Victor said:
Larry said:
Victor said:
Larry I Smith wrote:

Clark S. Cox III wrote:


On 2005-06-09 15:34:28 -0400, Larry I Smith
<[email protected]>
said:


[...]
It is different. For one thing the args to function calls are
pushed on to the stack in different order in C vs C++.


Where does either standard say anything about the order of parameters
pushed on the "stack", or even if they are pushed on a stack at all?




See my 2 replies to Victor for the details.

I pains me to see your common sense go along with your memory...


Huh? Did you read the docs I ref'd in my last reply to you
(the one posted AFTER the 'memory' comment)?

Of course I did. Did you? Do it again. Read the top half of the page 3
and tell me where does it say that the order of arguments for a C++
function call is _reverse_ compared to a C function call.

Once you've done that, explain what your reply to me has to do with the
C++ _standard_language_, which makes no claim WHATSOEVER how (in what
order and where) arguments are passed to the function.

V

You are correct - I was wrong on the 'reverse' part of the comment.
It's been 12 years since I performed that task. :)

I was correct concerning the stack layout and who cleans up the
stack (the caller in C, the called function in C++). The 2nd
article I ref'd goes into more detail about the call stack layout
differences ('__cdecl' versus 'thiscall'). Although the 2nd
article is specific to MS VC, most compilers have similar
diff's between the C and C++ call stack layout.

http://www.codeproject.com/cpp/calling_conventions_demystified.asp

We've gotten way out in left field here from the OP's original
question:

"Is there a difference between the object code that is generated
when compiling C code as C versus compiling the same code as C++?"

The answer is yes.

The OP's question itself is not addressed (as far as I know) by
the C++ Language standard. Yet, with most compilers, there is a
significant difference in both naming and call stack layout between C
and C++ complied object modules. That's one of the primary reasons
for the 'extern "C"' type construct - so the compiler can emit the
correct calling code.

I think we've exhausted this subject.

Regards,
Larry
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top