Apologies if the question seems too obvious or simple. Unfortunately, after going through a bunch of threads and googling about typedef coupled with attribute prefix, I am still not able to it figure out.
I have a following snippet of code in a (supposedly) portable app -
#ifdef WIN32
#define MY_PREFIX __declspec(dllexport)
#else
#define MY_PREFIX __attribute__((visibility("default")))
#endif
typedef MY_PREFIX bool some_func(void);
So my question is this -
1) What is that typedef exactly doing?
2) The code compiles fine on VS2008, but on G++ (gcc-4.1), I get a warning
"‘visibility’ attribute ignored"
Is there any way I can remove that warning? (Omitting -Wattributes is not an option)
Thanks!
AFAIK in GCC visibility attribute for function type cannot be "wrapped" into a typedef-ed type. The compiler assumes that this visibility attribute applies to the typedef-name itself. And GCC does not support visibility for typedef names (and it is not what you need anyway).
I'd say that instead of trying to wrap the declspec/attribute into the typedef, it should be specified explicitly at the point of function declaration. As in
#ifdef WIN32
#define MY_PREFIX __declspec(dllexport)
#else
#define MY_PREFIX __attribute__((visibility("default")))
#endif
typedef bool some_func(void);
MY_PREFIX some_func foo; // <- actual declaration
This will, of course, make is less clean, since instead of specifying MY_PREFIX once inside the typedef it should now be specified in every function declaration. But that's probably the only way to make it work, unless I'm missing something.
Related
I am using mingw to compile C++ code on OSX for Windows. The C++ code is auto generated and includes MS Visual Studio-specific code:
class __declspec(novtable) SomeClass
When I compile, I get lots of warnings:
warning: ‘novtable’ attribute directive ignored [-Wattributes]
I want to suppress these warnings. Mingw does not support the -Wno-microsoft option, so I thought I might be able to get __declspec(notable) to be treated as an identifier pointing to an empty string and have the pre-processor remove it.
i.e.
#define __declspec(novtable)
However, this is treated as a re-definition of the __declspec() macro, which is not the desired behaviour.
Is there a way to get the pre-processor to treat __declspec(novtable) as an identifier, or otherwise suppress this warning? (The offending auto-generated code cannot be modified).
Presumably the compiler has this definition in effect
#define __declspec(x) __attribute__((x))
and also recognizes some (not all) Microsoft-specific attributes like dllexport and dllimport. The following only makes sense if the above hypothesis is true.
You can use
#undef __declspec // to suppress a meessage about macro redefinition
#define __declspec(x) // nothing
(perhaps suitably #ifdefed so as not to break compatibility with MSVC).
This will kill the whole __declspec feature, not just __declspec(novtable). If this is not what you need, read on.
If you only need to kill __declspec(novtable) and leave all the other attributes intact, try this
#define novtable // nothing
The __attribute__ directive may contain a possibly empty list of attributes, so __declspec(novtable) will presumably translate to __attribute__(()), which is perfectly OK. This will also kill all other occurrences of the identifier novtable. If it does occur in any other context, which is not too likely but possible, this option won't work fro you.
Another possibility is to take over the entire feature.
#undef __declspec
#define __declspec(x) my_attribute_ # x
#define my_attribute_dllexport __attribute__((dllexport)) // or whatever you need
#define my_attribute_dllimport __attribute__((dllimport)) // or whatever you need
// ... same for all attributes you do need
#define my_attribute_novtable // nothing
// ... same for all attributes you don't need
Define your __declspec(novtable) with some macro:
#define DECL_SPEC __declspec(novtable)
After that you can use it as:
class DECL_SPEC SomeClass
And redefine DECL_SPEC as empty when required:
#ifdef __MINGW32__
#define DECL_SPEC
#else
#define DECL_SPEC __declspec(novtable)
#endif
typically #define would be used to define a constant or a macro. However it is valid code to use #define in the following way.
#define MAX // does this do anything?
#define MAX 10 // I know how to treat this.
So, if I #define MAX 10, I know my pre-processor replaces all instances of MAX with 10. If someone uses #define MAX by itself however with no following replacement value, it's valid. Does this actually DO anything?
My reason for asking is that I am writing a compiler for c in c++ and handling preprocessor directives is required but I haven't been able to find out if there is any functionality I need to have when this occurs or if I just ignore this once my preprocess is done.
My first instinct is that this will create a symbol in my symbol table with no value named MAX, but it is equally possible it will do nothing.
As an add in question which is kind of bad form I know, but I'm really curious. Are there situations in real code where something like this would be used?
Thanks,
Binx
A typical example are header guards:
#ifndef MYHEADER
#define MYHEADER
...
#endif
You can test if something is defined with #ifdef / ifndef.
It creates a symbol with a blank definition, which can later be used in other preprocessor operations. There are a few things it can be used for:
1) Branching.
Consider the following:
#define ARBITRARY_SYMBOL
// ...
#ifdef ARBITRARY_SYMBOL
someCode();
#else /* ARBITRARY_SYMBOL */
someOtherCode();
#endif /* ARBITRARY_SYMBOL */
The existence of a symbol can be used to branch, selectively choosing the proper code for the situation. A good use of this is handling platform-specific equivalent code:
#if defined(_WIN32) || defined(_WIN64)
windowsCode();
#elif defined(__unix__)
unixCode();
#endif /* platform branching */
This can also be used to dummy code out, based on the situation. For example, if you want to have a function that only exists while debugging, you might have something like this:
#ifdef DEBUG
return_type function(parameter_list) {
function_body;
}
#endif /* DEBUG */
1A) Header guards.
Building on the above, header guards are a means of dummying out an entire header if it's already included in a project that spans multiple source files.
#ifndef HEADER_GUARD
#define HEADER_GUARD
// Header...
#endif /* HEADER_GUARD */
2) Dummying out a symbol.
You can also use defines with blank definitions to dummy out a symbol, when combined with branching. Consider the following:
#ifdef _WIN32
#define STDCALL __stdcall
#define CDECL __cdecl
// etc.
#elif defined(__unix__)
#define STDCALL
#define CDECL
#endif /* platform-specific */
// ...
void CDECL cdeclFunc(int, int, char, const std::string&, bool);
// Compiles as void __cdecl cdeclFunc(/* args */) on Windows.
// Compiles as void cdeclFunc(/* args */) on *nix.
Doing something like this allows you to write platform-independent code, but with the ability to specify the calling convention on Windows platforms. [Note that the header windef.h does this, defining CDECL, PASCAL, and WINAPI as blank symbols on platforms that don't support them.] This can also be used in other situations, whenever you need a preprocessor symbol to only expand to something else under certain conditions.
3) Documentation.
Blank macros can also be used to document code, since the preprocessor can strip them out. Microsoft is fond of this approach, using it in windef.h for the IN and OUT symbols often seen in Windows function prototypes.
There are likely other uses as well, but those are the only ones I can think of off the top of my head.
It doesn't "do" anything in the sense that it will not add anything to a line of code
#define MAX
int x = 1 + 2; MAX // here MAX does nothing
but what an empty define does is allow you to conditionally do certain things like
#ifdef DEBUG
// do thing
#endif
Similarly header guards use the existance of a macro to indicate if a file has already been included in a translation unit or not.
The C Preprocessor (CPP) creates a definitions table for all variables defined with the #define macro. As the CPP passes through the code, it does at least two things with this information.
First, it does a token replacement for the defined macro.
#define MAX(a,b) (a > b) ? (a) : (b)
MAX(1,2); // becomes (1 > 2) ? (1) : (2);
Second, it allows for those definitions to be searched for with other preprocessor macros such as #ifdef, #ifndef, #undef, or CPP extensions like #if defined(MACRO_NAME).
This allows for flexibility in using macro definitions in those cases when the value is not important, but the fact that a token is defined is important.
This allows for code like the following:
// DEBUG is never defined, so this code would
// get excluded when it reaches the compiler.
#ifdef DEBUG
// ... debug printing statements
#endif
#define does a character-for-character replacement. If you give no value, then the identifier is replaced by...nothing. Now this may seem strange. We often use this just to create an identifier whose existence can be checked with #ifdef or #ifndef. The most common use is in what are called "inclusion guards".
In your own preprocessor implementation, I see no reason to treat this as a special case. The behavior is the same as any other #define statement:
Add a symbol/value pair to the symbol table.
Whenever there is an occurrence of the symbol, replace it with its value.
Most likely, step 2 will never occur for a symbol with no value. However, if it does, the symbol is simply removed since its value is empty.
I am reading a C++ header file, in which there writes:
class CLASSEXPORT skExecutable : {.....}
A comment says that CLASSEXPORT is a macro expansion and then I find where CLASSEXPORT is defined.
#define CLASSEXPORT
And that's all..I feel confused about this..What does CLASSEXPORT represent in this sense? And how to understand the class skExecutable?
In your case, CLASSEXPORT is expanded to nothing (probably because it is not needed to expand it into something meaningful in your exact configuration), so your class will just be a class skExecutable {<...>};. This approach is commonly used for import/export directives, e.g. in the following snippet an appropriate directive will be places depending on whether COMPILING_DLL macro is defined:
#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class DLLEXPORT MyClass
{
};
Just to clear some stuff up: CLASSEXPORT is a macro. Macro expansion is a process, performed prior to compilation, during which all macros are replaced with whatever they are defined as.
In your case, I suspect that CLASSEXPORT is there to allow all classes that are declared in that way to be exported to some kind of shared library if the need arises in the future. Then that CLASSEXPORT would be defined as something like
#define CLASSEXPORT __declspec(dllexport)
and you could use skExecutable directly from a shared library.
I'm working on existing C++ code, which is using a kind of API.
While browsing the code I found a strange syntax that I saw now for the first time and I can't figure out what it does or how such is called.
It goes like this:
class KINDA_API foobar : public foo {
// Some class declarations
};
Everything after foobar is understandable for me. But what means that KINDA_API? What does this do? Is that any kind of advanced derivation or something like that?
Maybe there is any other Thread that answers this, and I also searched for it, but I don't even know how this is called ^^'
Usually when you see OMGWFT_API declarations in this exact way, this is a 'magic switch' for building a library in correct "mode":
static linking - OMGWFT_API replaced by "" (empty string)
dynamic linking - DLL - OMGWFT_API replaced by declspec(dllexport)
dynamic linking - EXE - OMGWFT_API replaced by declspec(dllimport)
i.e.
#ifdef BUILD_ME_AS_STATICLIB
#define OMGWFT_API
#else
#ifdef BUILD_ME_AS_DLL
#define OMGWFT_API declspec(dllexport)
#else
#define OMGWFT_API declspec(dllimport)
#endif
#endif
This is of course just an sketch of example, but I think you get the point now. Keywords are taken from MSVC not GCC< because I accidentially happen to remember them.
The "BUILD_ME_AS...." macros would be then defined via project options or -D command line switch.
However, it the OMGWFT_API can be set to have any meaning, so be sure to grep/search for a #define that sets this.
I guess it is a #define-d macro that does some "magic" before compile.
If you look through the existing call you are likely to find somthing like:
#ifdef _WIN32
#define KINDA_API <windows specific attribute>
#elif __linux
#define KINDA_API <linux specific attribute>
etc...
These macros are more likely conditioned on compilers and/or their versions rather than operating system but you get the idea...
I would like something like:
#define C_OR_CPP(C__, CPP__) #ifdef __cplusplus\
CPP__\
#else\
C__\
#endif
Is it possible?
Maybe some dirty hack with #include ?
Reason:
I make a header where a struct uses a member variable of type vector<stuff>*, but in C i want it to simply be void*, you know.
TIA
What's the problem with
#ifdef __cplusplus
#define C_OR_CPP(C, CPP) CPP
#else
#define C_OR_CPP(C, CPP) C
#endif
(Leaving names with double underscore to the implementation per phresnel remark)
My English is poor, and I'm sorry for language mistakes and typos if any.
If #ifdef must not wrap the macro invocation, there is a solution not so graceful.
g++ only:
You may try this in selective occasions. But if there are commas in a or b, workarounds are still needed.
It's simply based on the fact that __cplusplus is defined to "1" when in a C++ environment and remains itself while not.
#define SELECT1(a, b) a
#define SELECT__cplusplus(a, b) b
#define xcat(a,b) a##b
#define concat(...) xcat(__VA_ARGS__)
#define C_OR_CPP(C, CPP) concat(SELECT, __cplusplus)(C, CPP)
C_OR_CPP(1, 2)
Other Environments
Check the __cplusplus macro, a compiler that comforming to standard C++ should generate
#define __cplusplus value
and value should >= 199711L
Not in C++. But you can
#ifdef __cplusplus
# define CPP
#else
# define C
#endif
I assume this is just a pathological example by you. Note also that double underscore is reserved to library implementors (see 17.6.4.3.2 Global names).
vector, but in C i want it to simply be void, you know.
So, what speaks against a solution like
struct Foo {
#ifdef __cplusplus
...
#else
...
#endif
};
or what speaks against providing different APIs for different programming languages?
AProgrammer already given you the right answer, but the answer to the "is it possible" part of the question is no. Macro expansion doesn't occur until after all preprocessor directives have been handled, so any macro that expands into a #define or #ifdef will be passed to the compiler as regular source text, which will cause the compiler to yak.