I wrote a logging mechanism with several log levels.
LOG_FATAL(s)
LOG_ERROR(s)
LOG_WARN(s)
...
Now I want to be able to activate or deactivate the logging for some modules.
What I do now:
#ifdef MOUDLE_LOG_ON
MODULE_LOG_FATAL(s) LOG_FATAL(s)
MODULE_LOG_ERROR(s) LOG_ERROR(s)
MODULE_LOG_WARN(s) LOG_WARN(s)
...
#else
MODULE_LOG_FATAL(s)
MODULE_LOG_ERROR(s)
MODULE_LOG_WARN(s)
...
#endif
Is there a way to place the prefixing in a macro to use it like this:
SETUPLOGGING(MODULE)
I am wondering if using macros and inline functions could solve your issue:
void inline LOG_FATAL(const char *s)
{
printf("%s\n", s);
}
#define SETUPLOGGING(x) \
void inline x ## _LOG_FATAL(const char *s) { LOG_FATAL(s); }
SETUPLOGGING(MODULE)
int main()
{
MODULE_LOG_FATAL("hello");
}
After preprocessing, this produces:
void inline LOG_FATAL(const char *s)
{
printf("%s\n", s);
}
void inline MODULE_LOG_FATAL(const char *s) { LOG_FATAL(s); }
int main()
{
MODULE_LOG_FATAL("hello");
}
Macros can't define new macros. And when defining a macro, it isn't possible to build its name from other macro, so you can't use the common work around of including a file which defines what you want.
You could use a macro to define which include file you were going to use, but then, why not use an include file and use the macro in there?
Related
The following is some background as to what I want to do and why. The actual question is at the very bottom...
I have an API that has some format.
For instance
int f(void *str1, void *str2) {...}
I want to reimplement the system behind the API so that it can be a drop in replacement for the old system. However it turns out that str1 is now unnecessary and moreover doesn't make sense to have if you're aware that you're using my new system. Therefore, I want to be able to expose the underlying API that makes sense:
int f_internal(void *str2);
Right now I have code that looks like this:
#ifdef USE_INTERNAL
#define INTERNAL(sym) sym##_internal
#else
#define INTERNAL(sym) sym
#endif
extern "C" {
#ifndef USE_INTERNAL
int f(void *str1, void *str2){
return INTERNAL(f)(str2);
}
#endif
SOME_ATTRIBUTES
int
INTERNAL(f)(void *str2){
... // actual content
} EXPORT_FUNCTION_MACRO(INTERNAL(f), 1);
}
The effect is if I define USE_INTERNAL, a call to f(a) works, but I don't define it then we have to use the f(a, b).
The problem I am encountering is that EXPORT_FUNCTION_MACRO itself defines another function name but doesn't evaluate INTERNAL(F) first. This results in the message
dir: error: pasting ")" and "_" does not give a valid preprocessing token
INTERNAL(sym) \
--- NOTE--- EXPORT_FUNCTION_MACRO takes args 'sys' and 'n'
other_dir: note: in definition of macro ‘EXPORT_FUNCTION_MACRO’
void _example##sym##_##n(void) {} \
WHAT I WANT TO DO:
I want to have a compile flag that can change the number of arguments needed to call something.
Maybe something like (if it existed)
using f(a, b) = f_internal(a);
Any ideas?
This results in the message
To fix the message let macro arguments expand before concatenating them.
#define EXPORT_FUNCTION_MACRO_X(sys, n) EXPORT_FUNCTION_MACRO(sys, n)
EXPORT_FUNCTION_MACRO_X(INTERNAL(f), 1);
You could achieve that with a macro in the C part:
#define f(...) CONCAT(f, NUM(__VA_ARGS__, 2, 1)) (__VA_ARGS__)
#define CONCAT(X, Y) CC(X, Y)
#define CC(X, Y) X ## Y
#define NUM(X, Y, N, ...) N
#ifdef __cplusplus
extern "C"
#endif
void f_internal(void* str);
// specifically compiled for C or C++ anyway (and most likely inlined)
// -> no need for extern "C" for these:
void f1(void* str) { f_internal(str); }
void f2(void* unused, void* str) { f_internal(str); }
The macro f would select the correct function out of f1 and f2, which again would call f_internal with the correct argument. Works for both C and C++. If you prefer, you could still just provide two overloads for C++ separately and let only the C people deal with the macros.
I doubt one could call that 'elegant'; if you want to qualify as 'ugly' – up to you. But at least it works...
The following code behaves like this:
If USE_INTERNAL is defined, defines an inline (c++) / static (c) function int f(void* str).
Otherwise, defines an inline (c++) / static (c) function int f(void* str1, void* str2).
Both functions are trampolines to the actual (int f_internal(void* str)) function.
Note that since the functions are defined in the header, inline (c++) / static (c) is required to keep them from violating the ODR rule (I am a c++ person, so I don't know any way better than static to achieve this in c. If there is, please let me know).
#ifdef __cplusplus
extern "C"
#endif
int f_internal(void* str);
#ifdef USE_INTERNAL
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str1, void* str2) {
return f_internal(str2);
}
#else
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str) {
return f_internal(str);
}
#endif
I am trying to add test functions in a suite on both windows and linux machines. On linux machines i want the real functions to be added and on windows machine i want the dummy UnsupportedFunction to be added so that i can have same number of functions on both environments.
I have the following code
void UnsupportedFunction(struct1* test)
{
//dummy function in C
}
// following functions defined else where and gets added only if its linux box
#if ENV_LINUX
extern void linuxOnlyFunc1(struct1* test);
extern void linuxOnlyFunc2(struct1* test);
extern void linuxOnlyFunc3(struct1* test);
extern void linuxOnlyFunc4(struct1* test);
#endif
static struct1* addTest(params, TestFunction fnPtr) {
...
}
static void addTestToSuite (struct1* suite,
input devices,
TestFunction testFunction,
const char* testName,
const char* testDescription)
{
TestFunction fnPtr = UnsupportedFunction;
#if ENV_LINUX
fnPtr = linuxOnlyFunc1;
#endif
LinWB_Util_AddTest(params, fnPtr);
}
the issue is since i have lot of tests to be added to the suite, i have to make an ugly if-defines on all the entries. To get rid of these i have to abstract with a function call but, those externed functions doesnt exist on windows env and i end up getting compiler errors or warnings (considered errors).
how can one design this in a better way ?
How about something like
#if ENV_LINUX
extern void linuxOnlyFunc1(struct1* test);
extern void linuxOnlyFunc2(struct1* test);
extern void linuxOnlyFunc3(struct1* test);
extern void linuxOnlyFunc4(struct1* test);
#else
#define linuxOnlyFunc1 UnsupportedFunction
#define linuxOnlyFunc2 UnsupportedFunction
...
#endif
I haven't tested this, so it might need some tweaking, but you could do something like this:
#if ENV_LINUX
#define linux_only(x) extern void x(struct1* test);
#else
#define linux_only(x) inline void x(struct1* test) { UnsupportedFunction(test); }
#endif
linux_only(linuxOnlyFunc1);
linux_only(linuxOnlyFunc2);
linux_only(linuxOnlyFunc3);
linux_only(linuxOnlyFunc4);
You could use include files to store your function declarations. Thus you dont't have to write them into every source file. And if the functions turn out to be undefined, just write such functions.
upon request, I elaborate.
You create a file called "fakefuns.h" which contains your function declarations:
#if ENV_LINUX
extern void linuxOnlyFunc1(struct1* test);
extern void linuxOnlyFunc2(struct1* test);
extern void linuxOnlyFunc3(struct1* test);
extern void linuxOnlyFunc4(struct1* test);
#endif
Then you can include these definition in every source file by adding
#include "fakefuns.h"
into the source file, preferably near to the first line. And in one source file, you actually implement these functions, both for Linux and Windows. And if they should not to any work in Windows, the implementations will be very simple.
I'm trying to implement logging which produce no overhead when not needed (i.e. no method call should be performed at all). I want NO overhead because it's low-latency code. I just added #define ENABLE_LOGS to my header class and now it looks like that (you can ignore details)
#pragma once
#include <string>
#include <fstream>
#define ENABLE_LOGS
namespace fastNative {
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false);
~Logger(void);
void Error(std::string message, ...);
void Debug(std::string message, ...);
void DebugConsole(std::string message, ...);
void Flush();
static Logger errorsLogger;
static Logger infoLogger;
private:
FILE* logFile;
bool debugEnabled;
};
}
Every time I need to use some method I should surround it like that:
#ifdef ENABLE_LOGS
logger.Debug("seq=%6d len=%4d", seq, length_);
#endif
It's error-phrone (i can forgot to surround) and makes code dirty. Can I fix my code somehow not to use #ifdef every time?
In C# I like Conditional I guess I need something like that for c++.
First of all it would make sense to have a look to see what's out there already. This is a common problem and many people will have solved it before. E.g., see stackoverflow question C++ logging framework suggestions, and Dr Dobbs A Highly Configurable Logging Framework In C++.
If you do roll your own, you should get some good ideas from having done this. There are several approaches I've used in the past. One is to make the statement itself conditionally defined
#ifdef ENABLE_LOGS
#define LOG(a,b,c) logger.Debug(a, b, c)
#else
#define LOG(a,b,c)
#endif
Another approach is to conditionally define the logging class itself. The non-logging version has everything as empty statements, and you rely on the compiler optimizing everything out.
#ifdef ENABLE_LOGS
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false);
~Logger(void);
void Error(std::string message, ...);
void Debug(std::string message, ...);
void DebugConsole(std::string message, ...);
void Flush();
static Logger errorsLogger;
static Logger infoLogger;
private:
FILE* logFile;
bool debugEnabled;
};
#else
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false) {}
~Logger(void) {}
void Error(std::string message, ...) {}
void Debug(std::string message, ...) {}
void DebugConsole(std::string message, ...) {}
void Flush() {}
};
#endif
You could put your Logger implementation for ENABLE_LOGS in a cpp file under control of the macro. One issue with this approach is that you would want to be sure to define the interface so the compiler could optimize everything out. So, e.g., use a C-string parameter type (const char*). In any case const std::string& is preferable to std::string (the latter ensures there's a string copy every time there's a call).
Finally if you go for the first approach, you should encapsulate everything in do() { ... } while(0) in order to ensure that you don't get bizarre behavior when you use your macro where a compound statement might be expected.
There is one way (the way llvm does) to do this using macros.
#ifdef ENABLE_LOGS
#define DEBUG(ARG) do { ARG; } while(0)
#else
#define DEBUG(ARG)
#endif
Then use it as:
DEBUG(logger.Debug("seq=%6d len=%4d", seq, length_););
What I often see, is to use the #define to actually define the log calls, eg:
#define LOG_DEBUG(msg) logger.Debug(msg);
But you want to wrap the defines in a block that enables or disables your logging:
#ifdef ENABLE_LOGS
#define LOG_DEBUG(msg) logger.Debug(msg);
#else
#define LOG_DEBUG(msg)
#endif
You can call LOG_DEBUG anywhere in your code. If the logging is disabled, calling LOG_DEBUG ends up as a blank line in your final code.
A nice old trick is:
#ifdef ENABLE_LOGS
#define LOG Logger.Debug
#else
#define LOG (void)sizeof
#endif
Then the code:
LOG("seq=%6d len=%4d", seq, length_);
will expand to:
Logger.Debug("seq=%6d len=%4d", seq, length_);
that does the log. Or:
(void)sizeof("seq=%6d len=%4d", seq, length_);
that does absolutely nothing. It doesn't even evaluate the function arguments!!!
The trick is that the first version uses the comma as argument separator in a function call. In the second version, however, it is a unevaluated comma operator.
However, some compilers may give spurious warnings about unreachable code.
You could put the #ifdef inside the body of the individual functions. This avoid the code duplication issue in TooTone's answer.
Example:
void fastNative::Logger::Debug(std::string message, ...)
{
#ifdef ENABLE_LOGS
// do the actual logging
#endif
}
If ENABLE_LOGS isn't defined, this function doesn't do anything. What I would suggest is you pass a const char* instead of std::string to these method. That way, if ENABLE_LOGS is not defined, you wouldn't have to rely on the compiler to not create redundant std::string objects.
I need a macro to pass the __FILE__ and __LINE__ to a function which has default arguments. This has opened up a can of worms, since default args with macros are either not possible or very messy, and I need to support both GCC and MSVC if possible:
class Class
{
#ifdef _DEBUG
int Function(int a, int b = 10, int c = 20) { return a + b + c; }
#else
int DebugFunction(const char* filename, int lineNo, int a, int b = 10, int c = 20)
{
printf("%s (%i) a:%i b:%i c:%i\n", filename, lineNo, a, b, c);
return a + b + c;
}
//Not possible
#define Function( DebugFunction(__FILE__, __LINE__
#endif
}
I've tried \escaping the ( to no avail. The codebase is huge, so fixing up the missing default args or creating multiple macros isn't a popular option.
Any solutions?
You can make a variadic macro:
#define Function(...) DebugFunction(__FILE__, __LINE__, __VA_ARGS__)
Since you cannot "overload" macros, this might be your best bet.
One option would be to rewrite your main function Function like this:
int Function(const char* filename, int lineNo, int a, int b = 10, int c = 20)
{
#ifdef _DEBUG
printf("%s (%i) a:%i b:%i c:%i\n", filename, lineNo, a, b, c);
#endif
return a + b + c;
}
That way, all the calls go to the same function, but the behavior of that function depends on whether or not you have the _DEBUG flag set. This bypasses the issue of default arguments, since you just have a normal function call with conditional code inclusion rather than a macro that might need many arguments.
Hope this helps!
I'm not quite sure I understand what you're trying to do, but would a variadic macro do the trick?
Not a big c++ guy, but have you tried something like (in pseudocode)
#ifdef debug
#define Function(args) _Function(__file__, __line__, (args))
int _Function(char *file, int line, args) { /* code */ }
#else
#define Function(args) _Function(args)
int _Function(args) { /* code */ }
#endif
The function itself needs to be able to take multiple versions of arguments, of course; I don't really see any other way of doing this.
I need a macro to expand to a c++ comment, is that possible?
I've got this:
#define SLASH(x,y) x y
#define OUT SLASH(/,/)
int main(int argc, char *argv[])
{
OUT << "text";
return 0;
}
And need to expand to this:
{
// << "text";
return 0;
}
I've also tried this:
#define SLASH(x) /x
#define OUT SLASH(/)
But the result is still the same:
int main(int argc, char *argv[])
{
/ / << "text";
return 0;
}
No it's not possible because in C++ comments are removed before macros are expanded.
(See 2.1 of the standard, comment removal happens in phase 3, macro expansion in phase 4.)
What about replacing it with a function object that does nothing instead?
static class NullOutput {
public:
template <typename T>
const NullOutput &operator<<(T arg) const {
return *this;
}
} NullOutputObj;
#define OUT NullOutputObj
The net result is that the object is removed from the code and replaced by inlined template expansions, that are then optimized out as they do nothing. Result is absolutely no code overhead.
As others mentioned there is no guaranteed way to define the kind of macro you are looking for. Other ways to achieve results that are similar to what you seem to be trying to achieve are wrapping your output statement in a conditional block or define a custom output stream that just discarded all output. The two approaches may even be combined so that behaviour could be switched by changing a single macro definition.
Comments are removed from the source code before the preprocessor runs. So you cannot do this.
an alternate to what you want to achieve would be this :
http://donjaffer.blogspot.in/2012/09/dprintf-debug-macro-in-c.html
#define DEBUG // comment if you do not want the debug statments to appear.
#ifdef DEBUG
#define DPRINTF(fmt, ...) \
do { printf("my_file: " fmt, ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
wherever you are trying to print the statements, instead of COUT << you can use
DPRINTF("Your text here\n");