Using C functions in a C++ program

R

ruffiano

A colleague of mine who is a C developer wrote several functions in C
which I now need to invoke in my C++ application. This is normally not
a problem except that the header file that he wrote contains also
several structures and #defines, which I need to use in my C++
application.

What is the best way to use the C functions, structures and defines in
my code without upsetting the compiler / linker?

For the C functions I know I need to use extern "C" { ...}. But how do
I get to include the structures and the defines? If I include the
header file in my C++ code, then the linker will fail.

Any help is greatly appreciated.

Thanks.
 
N

Noah Roberts

ruffiano said:
A colleague of mine who is a C developer wrote several functions in C
which I now need to invoke in my C++ application. This is normally not
a problem except that the header file that he wrote contains also
several structures and #defines, which I need to use in my C++
application.

What is the best way to use the C functions, structures and defines in
my code without upsetting the compiler / linker?

For the C functions I know I need to use extern "C" { ...}. But how do
I get to include the structures and the defines? If I include the
header file in my C++ code, then the linker will fail.

You can embed the C functions and structures in a namespace:

namespace CFunctions {

#include "CHeader.h"

};

Now you refer to them as CFunctions::function() and such and it won't
clobber your global namespace with names you already have.

You can also use preprocessor stuff to undefine and redefine your
macros where needed. I don't know if push/pop and undef are standard
but they are rather common.
 
F

Frederick Gotham

ruffiano posted:
A colleague of mine who is a C developer wrote several functions in C
which I now need to invoke in my C++ application. This is normally not
a problem except that the header file that he wrote contains also
several structures and #defines, which I need to use in my C++
application.


You'll have your files like:

apple.hpp
table.hpp

apple.cpp
table.cpp
disk.cpp

Your colleague's source files should have the extension ".c" -- most
compilers take this to mean that it should be compiled as C. Make sure though
that you go through the compiler options, paying specific attention to
whether it's compiled as C89 or as C99.

What is the best way to use the C functions, structures and defines in
my code without upsetting the compiler / linker?
For the C functions I know I need to use extern "C" { ...}. But how do
I get to include the structures and the defines? If I include the
header file in my C++ code, then the linker will fail.


Why does the linker fail?
 
I

Ian Collins

Noah said:
You can embed the C functions and structures in a namespace:

namespace CFunctions {

#include "CHeader.h"

};

Now you refer to them as CFunctions::function() and such and it won't
clobber your global namespace with names you already have.
But then they will fail to link, assuming the C code is compiled with a
C compiler, all the symbols will be extern "C", not C++ mangled names.

Even if the C code is compiled with the C++ compiler, you will have to
conditionally include the namespace declaration for C++ compilation.

Better off just putting extern "C" round the inclusion of the header, or
better still conditionally included the wrapper in the header.
 
N

Noah Roberts

Ian said:
But then they will fail to link, assuming the C code is compiled with a
C compiler, all the symbols will be extern "C", not C++ mangled names.

Even if the C code is compiled with the C++ compiler, you will have to
conditionally include the namespace declaration for C++ compilation.

Better off just putting extern "C" round the inclusion of the header, or
better still conditionally included the wrapper in the header.

I misunderstood the problem. I figured he was dealing with names the
same as names he has.
 
R

ruffiano

Better off just putting extern "C" round the inclusion of the header,


Hello Ian, I apologize in advance if I misunderstood you, but are you
basically suggesting writing the following:

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

or better still conditionally included the wrapper in the header.
???
 
I

Ian Collins

ruffiano said:
Hello Ian, I apologize in advance if I misunderstood you, but are you
basically suggesting writing the following:

extern "C"
{
#include "CHeader.h"
}
Yes. Please reply inline, rather than top-posting.
in the header file, add

#ifdef __cplusplus
extern "C" {
#endif

before the definitions and

#ifdef __cplusplus
}
#endif

after them.

This is the usual way to make a header safe for inclusion in either C or
C++ code.
 
P

Pete Becker

Ian said:
Better off just putting extern "C" round the inclusion of the header,

Don't do that. It can cause horrible problems. The C header might pull
in other headers which, rightly, assume that they are not inside an
extern "C" block.

or
better still conditionally included the wrapper in the header.

Yup. Headers that will be used in both C and C++ need to conditionally
wrap their function prototypes in an extern "C" block:

#ifdef __cplusplus
extern "C" {
#endif

int my_funky_C_func(void);

#ifdef __cplusplus
}
#endif
 
G

Greg Comeau


IME, that forms should be avoided at almost all costs.
"funny things" start happening with typedef's, nested headers
and with compilers.

Only extern "C" what needs to be.

To quote Las Vegas: What happens in extern "C" stays in extern "C"
 
P

Pete Becker

Greg said:
IME, that forms should be avoided at almost all costs.
"funny things" start happening with typedef's, nested headers
and with compilers.

And the standard explicitly prohibits including standard headers inside
any extern declaration, which in turn means that this isn't allowed if
CHeader.h uses any standard headers.
 
R

ruffiano

ruffiano,
refer this link,

http://developers.sun.com/prodtech/cc/articles/mixing.html

hope it will be helpful,

Thanks for this article, which specifically addresses the problem I'm
dealing with. I also appreciate all the other suggestions. In the end,
I edited the header file as follows:

#ifdef __cplusplus
extern "C" {
#endif
.... /* body of header */
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif

P.S.: Is this the correct way to reply inline?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,265
Messages
2,571,317
Members
47,996
Latest member
LaurenFola

Latest Threads

Top