Solved

mixing C with C++

Posted on 2003-11-06
9
1,106 Views
Last Modified: 2008-02-01

I'm looking at and opting to modify code that has me in a quandry.

Consider

// file_a.h  
-----------------------------------------------------
#ifndef FILE_H
#define FILE_H

  int idx;
  int jdx;
  void DoSomething ();

#endif;

file_a.h has its appropriate C source (file_a.c)

There exists two files file_b and file_main with source and header respectively.  The source files are C source files and the header for BOTH includes "file_a.h"


With the exception of file_a.h and its C source file_a.c, I'm opting to modify file_b and main to use C++ constructs.  i.e Class etc.  So now

// file_b.cpp
-----------------------------------------------------
#include "file_a.h"   // note the include on file_a.h which has a C source file
class FOO
{

}

// file_main.cpp
-----------------------------------------------------
#include "file_a.h"  // note the include on file_a.h which has a C source file

// later
int main ()
{
  // stuff
}

Try compiling and I get multiple definition errors  for elements idx and jdx.   Note I'm trying not to change file_a.h and file_a.c

So I thought perhaps I could do

// file_b.cpp
-----------------------------------------------------
extern "C"
{
  #include "file_a.h"        
}
class FOO
{

}

// file_main.cpp
-----------------------------------------------------
extern "C"
{
  #include "file_a.h"        
}
int main ()
{

}

The end result, multiple declaration errors.
Tried..

#ifdef _cplusplus
extern "C"
{
#endif
  #include "file_a.h"

#ifdef _cplusplus
}
#endif

Still multiple declaration errors.

Now I realize this makes the code non portable but .. In any event, I'd like to access the elements (extern) in file_a.h in my cpp files without touching file_a.    The solution?

One other thing.
Suppose I had

class FOO
{
  public
    FOO() { }
    DoSomething ();
   :

};

Namemangling here means "FOO_Something" when viewed from the linker's perspective?  The impetus behind the name mangling has to do with operator overloading in ++ but I'm not seeing 'how so'.


As always thanks in advance for the assistance.
0
Comment
Question by:forums_mp
9 Comments
 
LVL 15

Assisted Solution

by:efn
efn earned 200 total points
ID: 9697683
You do need to do the 'extern "C"' stuff to be able to call DoSomething from the C++ files, but that is not related to the multiple definition errors.

Each time the compiler reads file_a.h, it thinks you are defining global variables with the same names.

I know you didn't want to touch file_a.h, but it is causing the problem.  The standard approach is to declare the variables as extern in the header file and define them in the .c file.

file_a.h:

extern int idx;

file_a.c:

int idx;

For an essay on name mangling, see:

http://www.tldp.org/HOWTO/C++-dlopen/theproblem.html

--efn
0
 

Author Comment

by:forums_mp
ID: 9697802

You're right, I just need to change file_a.h.   Problem solved.  However, with your approach how would file_main.cpp and file_b.cpp look at "idx and jdx".  externs?   I would have thought I'd just wrap them in the extern "C" stuff with the DoSomething() function.

Here's something i ran 'into'
In file_main.cpp I did
-----------------------------------------------------
#ifdef _cplusplus
extern "C"
{
#end if
  #include "file_a.h"  // include file_a here.

   extern int idx;
   extern int jdx;
   extern void DoSomething ();

#ifdef _cplusplus
}
#endif

In file_b.cpp
-----------------------------------------------------
#include "file_a.h"

   extern int idx;
   extern int jdx;
:
:

Makes sense?
0
 
LVL 15

Expert Comment

by:efn
ID: 9697839
I'm not sure I understand your question.  If file_a.h says

extern int idx;

and main.cpp has

#include "file_a.h"

then functions in main.cpp can refer to idx as a global variable defined somewhere else.  So there is no need for an additional redeclaration as you showed, although it won't break anything.

--efn
0
 

Expert Comment

by:singhi
ID: 9699007
i think the problem is that you are including the file "file_a.h" in bith the source and header files of the files 'file_b' and 'file_main'. just include the file "file_a.h" in the header files no need to include them in the source files. If the macro is there in the file, as you have shown in the code, it shouldn't give any problem even if the file is included multiple times.
I think there is some other problem, can you please paraphrase your question, giving more details.
And as far as looking of extern variables is concerned, the compiler just needs to know the declarataion of variables the looking up is done by the compiler. You need to link all your files together.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:forums_mp
ID: 9703148

Really what the issue amounts to is I got C and C++ files.  The C files have a header & source file I'd like to use in my C++ files.  I'll experiment with your approach which says include the C files in the header of the C++ files and let the inclusion guard handle the rest.

Ultimately as  efn pointed out i just need to modify the C header to declare using 'extern' at the front end.  (extern int idx, extern int jdx .. etc)

Then later in file_main.cpp and file_b.cpp use(define) as/where necessary.  For the function calls in the C header that I'd like access to in the C++ source I'll use the extern bit .   I think this is where my confusion came in and as such I tried using the two flavors

#ifdef _cplusplus
extern "C"
{
#end if

#ifdef _cplusplus
}
#end if

versus

'extern "C" { }

I was perusing the article in the link above and i'm still not sure what the difference is betwen the two flavors
0
 
LVL 15

Expert Comment

by:efn
ID: 9703427
The second flavor will only work with a C++ compiler--a C compiler won't know what 'extern "C"' means.  The first flavor allows you to use a single header file for both C and C++ includers, which is desirable.

--efn
0
 

Author Comment

by:forums_mp
ID: 9704244
A few minor confusion on my part.  There's still the extern "C" in the second flavor so how's it possible that a single header will suffice for both C and C++ includes?

Is it safe to state that we should put the 'include' between the endif and the ifdef _cplusplus when dealing with the first flavor?

It also sounds like the first flavor will do every thing you'd like to do. In essence the second flavor is rolled into the first ?
0
 
LVL 15

Accepted Solution

by:
efn earned 200 total points
ID: 9704431
> There's still the extern "C" in the second flavor so how's it possible that a single header will suffice for both C and C++ includes?

The second flavor is not the one that will work in both C and C++.  Only the first flavor will do that.  The #ifdefs in the first flavor rig it so only the C++ compiler sees the 'extern "C"' specifications.

> Is it safe to state that we should put the 'include' between the endif and the ifdef _cplusplus when dealing with the first flavor?

Yes, if you mean the first endif and the second ifdef, and you are talking about coding in a header file.  The first flavor works like this:

#ifdef _cplusplus
extern "C"
{
#endif

/* In here you put C declarations.  They can be in #included header files.  */

#ifdef _cplusplus
}
#endif

You only need this stuff in a header file.  You might use an include in this form if you had a C header file you didn't want to change and you wanted to wrap it in another header file that would work with either C or C++.

> It also sounds like the first flavor will do every thing you'd like to do. In essence the second flavor is rolled into the first ?

That's right, they both do the same thing, but only the first flavor makes it compatible with C.  The only reason you might want to use the second flavor is that it's simpler, so it would be reasonable to use it if you didn't care about C compatibility.

--efn
0
 
LVL 3

Assisted Solution

by:RJSoft
RJSoft earned 50 total points
ID: 9705418
#ifndef  MasterFile_h
#define MasterFile_h

extern "C"
{
#include "file_ah.h" //notice I have not changed this c header file
//so you can still compile it in c
}

//include your other c++ stuff

#endif

#include "Master.h" in your .cpp's files
#include file_ah.h in your c file.

RJSoft
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now