5

I know questions regarding extern "C" have been asked before but I am getting mixed signals and would like it if someone could point me to what the best practice is in the scenario below. I have written a driver for Linux and have several struct defined as well as some _IO, _IOR, and _IOW definitions for ioctl(...) calls. None of my structures contain any functions, below is an example struct, enum and ioctl that I use:

#ifdef __cplusplus
extern "C" {
#endif
enum Alignment
{
  Left = 0,
  Right = 1,
  Middle = 3
};

struct Data
{
  int Size;
  void* Address;
};

#define foo  _IOR(DRV_ID, 1, struct Data*);
#ifdef __cplusplus
}
#endif

My question is, do I need to add an extern "C" to this header? The header is defined in my driver which is written in C and used by user programs written in C++. I figure because there are no member functions or specific library function calls I do not need extern "C". Also, is it safe to change my enum to below without extern "C":

#ifdef __cplusplus >= 201103L
enum class Alignment
#else
enum Alignment
#endif
{
  Left = 0,
  Right = 1,
  Middle = 3
};

Edit:

My header is already wrapped in extern "C". I'm trying to understand if this is needed for items that do not call functions and name mangling is an issue.

user2205930
  • 1,046
  • 12
  • 26
  • @M.M "Your compiler might do something beyond what the standard says" Not if it tries to implement the standard. – n. m. could be an AI Jul 03 '16 at 23:49
  • @n.m. I changed my comment to an answer. But I'm not sure what you mean, every compiler does a lot of things that are neither required nor prohibited by the standard. – M.M Jul 03 '16 at 23:50
  • @M.M I don't see how the standard permits e.g. enums to meaningfully have language linkage. – n. m. could be an AI Jul 03 '16 at 23:59
  • @n.m. choice of underlying type is up to the compiler to some extent, maybe a compiler could say that if you use `extern "C"` then it will make the same choice in C++ that it would in C, for ABI compatibility – M.M Jul 04 '16 at 00:11
  • @M.M then `extern "C" enum x` will be incompatible with `enum x`, which would break conformant programs. – n. m. could be an AI Jul 04 '16 at 08:16
  • @n.m. conforming programs can't have `extern "C" enum x` anyway – M.M Jul 04 '16 at 08:27
  • @M.M of course they can, you can wrap an entire header in extern "C" with classes, templates, enums and anything else. Only functions and external variables are affected. – n. m. could be an AI Jul 04 '16 at 08:35

3 Answers3

4

in Standard C++ , extern "C" only affects: function types, function names and variable names. Not to enum definitions.

Your compiler might do something beyond what the standard says, you'd have to consult its documentation.

The conditional enum class is a bad idea. You might end up with the enum having a different size in C than in C++, leading to problems with interoperability. This isn't covered by either standard, but for interoperability it'd be best to make sure the exact same code is used for both languages, other than extern "C".

M.M
  • 138,810
  • 21
  • 208
  • 365
2

There is a conflict here:

your code goes like this:

#ifdef __cplusplus >= 201103L
enum class Alignment
#else
enum Alignment

but extern "c" should be put in the exact macro:

#ifdef __cplusplus
    extern "C" 
 #endif
 enum Alignment

the outcome, if you append both macros:

extern "C" enum class Alignment

but this is illegal, since C language doesn't knows such as declaration.

therefore, I guess that if you want to use extern "C", to be able to use the header from c, not only c++, you should gave up of the enum class and use old fashion enum type. if you decide to use the header only from c++, the extern "C" is not needed, and you can use enum class.

SHR
  • 7,940
  • 9
  • 38
  • 57
  • I see what you are getting at but my understanding is that `extern "C"` is meant to resolve name mangling from C++ which causes problems when calling a function. If I am using `struct` definitions without member functions then do I need to worry about name mangling? Using `enum class` is just a compiler understanding and shouldn't result in name mangling if I use the `enum` with either C or C++ because the `#ifdef` will take care of that. My entire header file is already wrapped in an `extern "C"` statement. – user2205930 Jul 03 '16 at 23:47
  • C++ name mangling is the same while you keep using the same compiler. C lang. doesn't support function overloading, therefore name mangling is not needed and the name can be used as is. the `extern "C"` just cause the function signature look like C, but you can use only C supported types. `extern "C"` can also help you if you load library at runtime and want to look for symbols by name, it just easier to use the name. for regular link if both are c++, `extern "C"` is not needed. – SHR Jul 04 '16 at 08:58
2

Name mangling is not important for data types. What you get from your library is pure binary data and they don't care how you name them. More important for your types is to have correct alignment and order.

Logman
  • 4,031
  • 1
  • 23
  • 35