14

I'm using an external C library inside a C++ project.

The header contains a struct with a variable named class:

#ifdef __cplusplus extern "C" { #endif struct something_t { ... sometype class; }; #ifdef __cplusplus } #endif 

g++ does not like this and complains about "error: expected identifier before ';' token".

What options do I have?

  1. I could rename class, but that's cumbersome and breaks upstream compatibility.
  2. I could ask the upstream project to rename the variable, but that may be difficult.
  3. I could redefine class in the header using the preprocessor: #define class class_ Are there any side effects?
  4. Any other suggestions?

What's the best way to handle this situation?

Result: Based on the prevailing preference for option 2, I finally chose to initiate a renaming in the upstream library.

8
  • 5
    Regarding possible solution 3, think what happens when you need the actual keyword class. The best long-term solution (IMO) is 2. Commented Oct 15, 2017 at 9:40
  • 1
    Redefining keywords is UB, so that's probably not the way to go. Commented Oct 15, 2017 at 9:41
  • 2
    Create a C wrapper and inside it rename it. Then use that wrapper in your C++ project. Commented Oct 15, 2017 at 9:43
  • Could you create a type with the same memory layout but slightly different names for use in C++? Commented Oct 15, 2017 at 9:43
  • 5
    Option 4 would be to write your own wrapper in C where you repackage the parameters and call the C library functions. Then only expose a proper interface to C++. Commented Oct 15, 2017 at 9:44

1 Answer 1

13

As others already mentioned in comments, the best option is to write another C API layer around that stuff, that uses the other API only internally.

Anything related to this offending struct definition should be exported through opaque pointers only.

In C++ you can use the cleaned up C-API then.


Here's a small sketch:

ThirdParty.h (contains offending code to compile with c++)

#ifdef __cplusplus extern "C" { #endif struct something_t { ... sometype class; }; struct something_t* CreateSomething(); // Does memory allocation and initialization void DoSomething(struct something_t* something); #ifdef __cplusplus } #endif 

MyApiWrapper.h

#ifdef __cplusplus extern "C" { #endif typedef void* psomething_t; struct psomething_t MyCreateSomething(); // Does memory allocation and initialization void MyDoSomething(psomething_t something); #ifdef __cplusplus } #endif 

MyApiWrapper.c

#include "ThirdParty.h" struct psomething_t MyCreateSomething() { psomething_t psomething = (psomething_t)CreateSomething(); return psomething; } void MyDoSomething(psomething_t something) { DoSomething((struct something_t*)psomething); } 

Regarding your considered solutions

  1. I could ask the upstream project to rename the variable, but that may be difficult

You certainly should report that bug to let them know. If it's a git-hub hosted project prepare a pull request.

Anyways be prepared that they might not be responsive timely, and you should always have the above mentioned "plan B". It will work regardless ...

  1. I could redefine class in the header using the preprocessor: #define class class_ Are there any side effects?

It could be a viable way, if any place where this particular symbol (class) appears is plain c code and no other parts of the 3rd party c code (e.g. as library) depends on that symbol (which is unlikely).

Sign up to request clarification or add additional context in comments.

9 Comments

While this is the best practical solution to the OP's immediate problem, it still needs to be reported as a bug to the people responsible for the original library or this nonsense will never get fixed.
@StephenG It's always better to have a plan B in such situation. In practice you'll often meet such in old code that has been leaving the company decades ago, or have some buggy but unmaintained 3rd party code (likely for old silicon for example).
@StephenG So would you accept bug reports against your C++ library telling you that you're using a restricted FORTRAN keyword and to please rename it despite the name being the best fit? We have to tell people that C and C++ are two different languages here all the time and this is just one consequence of this fact. Sure if the maintainer is nice they might want to make your life easier, but it certainly isn't a bug in the original project - it's a feature request.
@Voo Frankly anyone who does library coding and uses a name like "class" as a variable name needs their butt kicked - it's asking for problems. A library should try and use e.g. a prefix for variable names like this (e.g. foo_class and foo_handle for a library called foo). This is pretty basic programming common sense to try and avoid name clashes. Using a major language keyword is just doubly daft and I would personally consider it a bug. YMMV.
@Voo TBF they have these weird #ifdef __cplusplus guards in their header code. Regarding this strong hint it should be compilable with a c++ compiler, that can be considered a bug I'd say.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.