mixing C with C++


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.
forums_mpAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

efnCommented:
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
forums_mpAuthor Commented:

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?
efnCommented:
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
Exploring SharePoint 2016

Explore SharePoint 2016, the web-based, collaborative platform that integrates with Microsoft Office to provide intranets, secure document management, and collaboration so you can develop your online and offline capabilities.

singhiCommented:
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.
forums_mpAuthor Commented:

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
efnCommented:
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
forums_mpAuthor Commented:
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 ?
efnCommented:
> 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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RJSoftCommented:
#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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.