2

I am trying to write a C++ code where I call a C function, lets say hello_world() which in-turn calls a user-defined typename() function. When I include my C code in C++, there is a compilation error, I know that typename is a keyword in C++ but then to include C code, I'm using

extern "C" { #include "hello_world.h"}

in my C++ code, and still there is an error during compilation, any suggestions to avoid this and to compile the code, i would be grateful.

I cannot change the name of user defined typename() function to other name. so how to go about...?

The errors as such : In file included from New_test.cpp:19:0: ../tools/symbol.h:38:14: error: expected unqualified-id before ‘typename’ ../tools/symbol.h:38:14: error: expected initializer before ‘typename’ In file included from New_test.cpp:604:0: /usr/include/i386-linux-gnu/sys/poll.h: In function ‘int readpacket(channel*, void*, size_t)’: /usr/include/i386-linux-gnu/sys/poll.h:48:1: error: expected unqualified-id before string constant New_test.cpp:612:52: error: ‘poll’ was not declared in this scope

Trilok M
  • 681
  • 7
  • 21
  • 1
    In all likelihood, you can partition your headers such that `typename()` gets declared only in the C source from which it's invoked. Minimize the headers included by the C++ source. If you need to be able to invoke `typename()` from C++, consider changing your design to accept a function pointer. – Brian Cain Mar 03 '14 at 06:01
  • How can i restrict typename() to be declared only in C source. does using "extern "C" { #include "some_c.h"}" doesn't do it...? – Trilok M Mar 03 '14 at 06:06
  • the c only... but i call a C function which calls typename()... – Trilok M Mar 03 '14 at 06:10
  • Trilok, please share more info -- the bounty description makes it sound as if one or more of the answers are adequate but you want more evidence "drawing from credible and/or official sources." As the question is currently described, I think my answer is sufficient. If you have an [SSCCE](http://www.sscce.org/) it would help. – Brian Cain Mar 14 '14 at 17:32
  • @TrilokM, please specify what errors you are getting. – built1n Mar 16 '14 at 19:35

5 Answers5

7

You probably need something like this in your header file:

File: common_header.h

#ifdef __cplusplus
extern "C" {
#endif

extern void newname_typename();

#ifdef __cplusplus
}
#endif

and then a C-only compile unit:

#include "common_header.h"
#include "hello_world.h"
void newname_typename() {
   typename();
}

and in C++:

#include "common_header.h"

void do_stuff() {
  newname_typename();
}

and you need to ensure your Makefile ends up doing the following:

gcc c_only_code.c -o something1.o
g++ cplus_only_code.cxx -o something2.o
gcc something1.o something2.o <other stuff> -o binary  
6EQUJ5
  • 3,142
  • 1
  • 21
  • 29
  • should i use gcc cplus_only_code.c -o something2.o or g++ cplus_only_code.cpp -o something2.o...? – Trilok M Mar 03 '14 at 06:30
  • and whats the use of -o binary...? is it compulsory...? – Trilok M Mar 03 '14 at 06:31
  • sorry, fixed my typo. But that was just an example, it depends on your build system. Also (binary) was just an example for the executable. I was just trying to emphasise that you need to ensure the C code gets compiler by a C compiler and the C++ with a C++ compiler – 6EQUJ5 Mar 03 '14 at 06:33
  • In order to use "extern "C"{ #include "some.h" }" do i need to create a shared library of some.h ? – Trilok M Mar 04 '14 at 10:35
  • Because i tried use extern "C" { #include "some.h"} where my some.h has all the c functions defined and my cpp code is still non-compilable – Trilok M Mar 04 '14 at 10:37
  • your some.h C must be compatible with C++. There is no workaround, extern C doesnt help, it only permits C linkage. You must modify some.h or create a new compatible header file (common_header.h) as described above. – andreaplanet Mar 12 '14 at 15:11
5

Here's how you can partition things such that it should compile and link correctly. The C++ source file does not need to know that there's a function called typename().

File 'some_c.c':

#include "some_c.h"

void typename(); /* This declaration will suffice. */

void hello_world()
{
    typename();
}

File 'some_c.h'

/* References to typename()'s declaration must be deleted from this
** header file.  If it turns out that there are some other parts of the
** header file which somehow depend on the typename() declaration, you
** must separate this into multiple header files. 
*/
void hello_world();

File 'some_cpp.cpp':

/* Arguably this should show up in some_c.h, protected by
** #ifdef __cplusplus barriers.  But this should work too:
*/
extern "C" {
#include "some_c.h"
}

void SomeClass::someMethod()
{
    hello_world();
}
Brian Cain
  • 14,403
  • 3
  • 50
  • 88
  • /* References to typename()'s declaration must be deleted from this ** header file. If it turns out that there are some other parts of the ** header file which somehow depend on the typename() declaration, you ** must separate this into multiple header files. */ so where exactly i should declare typename(); – Trilok M Mar 03 '14 at 06:43
  • You must declare `typename()` in `some_c.c` or somewhere else not included by `some_cpp.cpp`. – Brian Cain Mar 03 '14 at 16:46
  • In order to use "extern "C"{ #include "some.h" }" do i need to create a shared library of some.h ? – Trilok M Mar 04 '14 at 10:34
  • Because i tried use extern "C" { #include "some.h"} where my some.h has all the c functions defined and my cpp code is still non-compilable. – Trilok M Mar 04 '14 at 10:37
  • No, you do not need a library, shared or otherwise. "still no-compilable" -- ok, why does it fail? – Brian Cain Mar 04 '14 at 16:58
3

extern "C" doesn't tell the c++ compiler to compile in C, but it tells to use C type linkage. Code incompatible with C++ will still generate errors. You must use the "bad" C header files only in C code. Create a new C header file which expose the required functions/code (compatible with C++ through wrapping/renaming) and use that new file C Header in the C++ code and with extern "C".

andreaplanet
  • 731
  • 5
  • 14
3

It's unlikely that there is an official answer to this question. The reason is that the extern "C" directive has an official usage and intent, and all of the authoritative documentation will discuss that usage and intent. You are trying to use extern "C" for something it wasn't intended for. An official document that discusses all unintended use cases would be hard to find. I submit that such a document would be infinitely long.

The intent of extern "C" is to allow C functions to call C++ functions and vice versa. The issue arises because by default C++ uses a different naming convention in object files than C does. C++ uses mangled function names, C uses straight forward function names. Also C++ may pass variables to a function differently than C. To allow C++ to call C functions (and vice versa), the extern "C" informs the compiler that it needs to use the C function calling conventions.

http://en.wikipedia.org/wiki/Extern_%22C%22#Linking_C_and_C.2B.2B_code

Therefore given the following requirements

1) a function named `typename` exists in a C source file
2) the function cannot be renamed
3) the function must be callable from a C++ source file

the only solution is to create a bridge file as fully explained in the post by Andrew McDonnell.

user3386109
  • 34,287
  • 7
  • 49
  • 68
0

This is for anyone with the same problem : In order to invoke a C function with function name being same as a defined keyword in C++ is to use extern "C" { /*function declaration */} and also you need to have a Shared Library.

Thank you all...!!!

Trilok M
  • 681
  • 7
  • 21