tags:

views:

94

answers:

1

Hi, I am getting following error p.c uses some of the function implemented in md4.c. p.c , when compiled with gcc works but it does not work with g++, gives undefined method error. Am I missing something obivious ?

[prafulla@ps7374 sample] $g++ -c -o md4.o md4.c 
[prafulla@ps7374 sample] $gcc -c -o md4.o md4.c
[prafulla@ps7374 sample] $g++ p.c md4.o
p.c: In function ‘int main()’:
p.c:5: warning: deprecated conversion from string constant to ‘char*’
/tmp/ccxE4q1J.o: In function `main':
p.c:(.text+0x3b): undefined reference to `MD4Init(MD4_CTX*)'
p.c:(.text+0x57): undefined reference to `MD4Update(MD4_CTX*, unsigned char*, unsigned int)'
p.c:(.text+0x6b): undefined reference to `MD4Final(unsigned char*, MD4_CTX*)'
collect2: ld returned 1 exit status
[prafulla@ps7374 sample] $gcc p.c md4.o

Here is my makefile

sample.out: sample.cc md4.o Makefile                                                                                                                         
            g++ -o sample.out sample.cc md4.o                                                                                                                              
            ./sample.out                                                                                                                                     
test.o: p.c                                                                                                                                                  
        g++ p.c md4.o                                                                                                                                        

md4.o:      md4.c md4.h                                                                                                                                      
            gcc -c -o md4.o md4.c   
+4  A: 

Because C++ supports function overloading, the C++ compiler must ensure that the linker sees two different names for void foo(int) and void foo(float). The most common way to do that is to encode information about the parameters into the names presented to the linker.
As C does not have overloading, there is also no need for the compiler to include information about the parameters in the names presented to the linker.

If you now naively try to link a C and a C++ object file, the linker will not be able to resolve all the names, because the object files use a different naming-scheme for the names they need and/or export.

As it is quite common to use C code from a C++ program, C++ has a mechanism of telling the compiler that certain functions should use the C naming-scheme instead of the C++ scheme: You declare these functions as extern "C" int bar(), or, if you have a bunch of C functions:

extern "C" {
  /* Function declarations here */
}

And where it says 'Function declarations here', you could just use #include to pull in a C header (although it is infinitely better to prepare the header itself for use in both C and C++).

To prepare a header for use in both C and C++, you first check that it does not use C++-specific keywords (such as class or new) and then you can add the following mantra to the header:

/* Include guard goes here */

#ifdef __cplusplus
extern "C" {
#endif

/* original content of the header */

#ifdef __cplusplus
}
#endif

/* #endif of the include guard here */
Bart van Ingen Schenau
Thanks a lot....!
Pvt
The obvious "Fix" is to compile either your entire program with C++, or none of it. Don't mix-and-match, or you'll have to use the extern "C" as above.
MarkR
@MarkR: Sometimes that will be impossible. For example, if you don't have control over the C code (as it is in an external library), or if it would be too much work to make the C code into valid C++ code.
Bart van Ingen Schenau
Ok, valid point, but if it was all mine, I'd compile all of it with C++ if possible.
MarkR