mixing C++ and C code elegantly

Hi

Does anyone have suggestions on how one can mix C++ and C code elegantly? Considering that when you are writing out method bodies,if one was to just call the C function (after making sure the header file was included in the current class), that would look a little out of place. Are there some elegant solutions to do this?

eg:
#include C.h
class A{
   public:
       int myfunc();
}

Inside A.cpp,

int A::myfunc(){
     my_c_function();
}  


C.h and C.c are C class header and C file that contain my_c_function().

Calling my_c_function like this from within the .cpp file might be ok for one or two calls but quickly gets ugly for scalable projects. Any ideas how to do this otherwise?
LuckyLucksAsked:
Who is Participating?
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.

phoffricCommented:
Your C.h should look something like this:
#ifndef C_H
#define C_H

#ifdef __cplusplus
extern "C" {
#endif

int my_c_function();
int other_c_functions();

#ifdef __cplusplus
}
#endif

#endif

Open in new window

When a .c file includes C.h, __cplusplus is not defined so the extern "C" will not be included.
When a .cpp file includes C.h, then the extern "C" will be included, and this informs the C++ compiler that the functions defined within the curly braces {...} are actually C-functions, and the C++ functions can now call the C functions directly.

For more information on combining C and C++, see:
https://isocpp.org/wiki/faq/mixing-c-and-cpp
0
phoffricCommented:
Note that without the extern "C", a C++ program will think that your C-function is a C++ function. Each C++ compiler has its own C++ name mangling approach for C++ functions. If the C++ compiler thinks that your function is a C++ function, then it will be looking for a C++ mangled function name rather than a (possible corresponding C-mangled) name.
See https://isocpp.org/wiki/faq/mixing-c-and-cpp
If you didn’t get your extern "C" right, you’ll sometimes get linker errors rather than compiler errors. This is due to the fact that C++ compilers usually “mangle” function names (e.g., to support function overloading) differently than C compilers.
0
sarabandeCommented:
note, the "extern C" is a helper to avoid c++ name mangling if you were using a self-written c-function or a self-written c library. however, if you add the c functions to your c++ project it makes no difference whether the c functions have got mangled names or not. with name mangling you don't have problems in a project where the c++ compiler was used for all .c sources as well since the mangled name was used everywhere. also there is an advantage doing so, since you can use the same function name with different argument lists.  commercial c libraries and those coming with the compiler already have the extern C switch in their header files.

mixing C++ and C code elegantly
you should try to avoid calling pure c functions in c++ if you want a straight and elegant design. for all commercial software you will find class libraries which are an equivalent (and better) replacement for using the c function. for your own c functions you could define them in a first step as public static functions of a helper class, say with name 'Helper'. then replace the c header by the new class header and compile.  the compiler will show you all calls as undefined and you can add Helper:: to the function. in a further step you may build more classes and probably have pointer type as argument for some functions which then could be turned to non-member functions of a new class (where 'this' can replace the pointer argument).

Sara
0

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
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

phoffricCommented:
>>  if you add the c functions to your c++ project it makes no difference whether the c functions have got mangled names or not. with name mangling you don't have problems in a project where the c++ compiler was used for all .c sources as well since the mangled name was used everywhere.

I'm not sure I follow this. Are you saying that you don't need extern "C" if using the same compiler for both C and C++ files? I am on a project with C, C++, and Fortran, and without the extern "C", I get linker errors of unresolved symbols (namely the C-functions). Name mangling is the culprit for these cases.
0
sarabandeCommented:
if the c functions were compiled with c++ compiler without 'extern C' clause, the linker module has a c++-mangled name like _xyz_MyCFunc_AbcGhj_. you then may call MyCFunc from any other c++ source or c source compiled with c++ compiler and it works.

a project with C, C++, and Fortran,
Fortran (of course) can't handle c++ names. so if you call c functions from fortran these c functions must be compiled either with ansi c compiler or with c++ compiler and extern C clause enabled. if you call fortran functions from c++ sources you also need prototypes where the extern c is active. same applies if you call c functions from c functions. if using ansi c compiler you are safe and if using c++ compiler without extern c you are safe as well. mixed mode will not work well and you have to use the method you described above in your comment to come out of this.

Sara
0
phoffricCommented:
@Sara,
If you are saying that if you use a C++ compiler to compile a C file which happens to be good enough to look like C++, then the mangling is purely C++, so no extern "C" is needed, then I agree. In that case, we actually do have a perfectly formed C++ program that just happens to look like C.

In my experience most legacy C modules usually need some tweaking to conform to C++ standard. In those cases, for C++ to call C, we need the extern "C" to quickly be able to absorb those C modules.
0
sarabandeCommented:
if you use a C++ compiler to compile a C file which happens to be good enough to look like C++
since c is a subset of c++ it would be able to compile any c file beside of very few exceptions where c++ is more strict than c, for example regarding implicit cast of a pointer returned by malloc. but these issues easily could be resolved.

I
n those cases, for C++ to call C, we need the extern "C" to quickly be able to absorb those C modules.
'extern C' only helps to avoid from c++ name mangling and thus allows to compile c functions with a c compiler and call them from c++. but if you have own c sources which no longer where used by an ansi c project, it would make much more sense to make a .cpp source out of it. then you could use same function name with different argument lists, can turn global variables to static members of  a structure or class, can use constructors and destructor for structures, can add operator functions to structures, use templates, use any container from standard library, and more. all this could be made step by step and only if you have to make an enhancement anyhow. you even could add the extern C for some functions which still were needed from a c environment.

Sara
0
evilrixSenior Software Engineer (Avast)Commented:
This sort of encapsulates some of the things already said above, so please - no points...

>> Does anyone have suggestions on how one can mix C++ and C code elegantly?
I'm not sure your question makes much sense. You don't need to do anything specific to call C functions in your code, since C functions are (ignoring a couple of minor caveats that you don't really need to be concerned with) C++ functions. There is no need to do anything special like implementing a forwarding function in a namespace (unless you want to).

Using "extern C" will ensure your C function has C rather than C++ linkage, but it's up to you whether you want to go that extra step. Your code will still build and link fine, regardless. It's only really important if you are writing a library and you want to export that function to be linked into a C program. If you are not doing that then you really don't need to worry about the external linkage at this point.

Basically, if you are writing code and building it with a C++ compiler, the code will be built as C++. It doesn't matter if it's a stand alone function and it doesn't matter if it only takes native C types, it'll still be compiled as a C++ function. If you only ever intend to use this in C++ projects then just put C out of your mind, you are coding in C++.
0
phoffricCommented:
Recently  I changed the name of several .c file to .cpp and they compiled fine. They were written well, and were fairly simple since they were just wrappers around FORTRAN modules.

Another consideration as to whether to use extern is ease of converting the C-code to C++. It is not always as easy as the above case.

Years ago when I tried to do that, the number of errors were enormous. This case was an entire set of files that I was told to use in our C++ program. Instead of spending a lot of time converting the .c files to C++, I just used the following approach in the .h headers:
#ifdef __cplusplus
extern "C" {
#endif

Open in new window

When compiling a .c file that uses this .h header, the C compiler skips over the extern "C" part.
When compiling a .cpp file that uses this .h header (so that C++ functions can call the C functions), the C++ compiler sees the extern "C" and uses the correct C calling names.

My vague recollection now was that there were about 100 files, and maybe 10,000 LOCs, so by not converting them to C++ saved me a good deal of conversion time. (I recall that they gave me a few weeks to do the job, but I was able to complete the integration in only a couple of days.)
0
LuckyLucksAuthor Commented:
Great! The static fn approach is a good idea.
0
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.