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?
class
, but that's cumbersome and breaks upstream compatibility.class
in the header using the preprocessor: #define class class_
Are there any side effects?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.
Variable names in C are made up of letters (upper and lower case) and digits. The underscore character ("_") is also permitted. Names must not begin with a digit. Unlike some languages (such as Perl and some BASIC dialects), C does not use any special prefix characters on variable names.
The $ sign is not allowed as the initial character of a user-defined variable. The period, the underscore, and the characters $, #, and @ can be used within variable names. For example, A. _$@#1 is a valid variable name.
Rules for naming a variable A variable name can only have letters (both uppercase and lowercase letters), digits and underscore. The first letter of a variable should be either a letter or an underscore. There is no rule on how long a variable name (identifier) can be.
The C rule of declaring variable name says that variable name starts with the underscore but not with other special characters, and it should not be any identifier name.
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
- 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 ...
- 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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With