This question already has answers here:
#ifdef inside #define
(6 answers)
Closed 9 years ago.
For some reason I need to define some nested definition. but the pre-processor
remove a part of my macro.
Look at following code:
#define SINGLE_ITERATION y+=xext[++xIndex]*H[hCounter--];
#define LOOP_ITERATION SINGLE_ITERATION \
SINGLE_ITERATION SINGLE_ITERATION \
SINGLE_ITERATION SINGLE_ITERATION \
SINGLE_ITERATION SINGLE_ITERATION \
SINGLE_ITERATION
#define DEBUG_CODE #ifdef MEMORIZE \
myOutput[xCounter]=y; \
#endif \
#ifdef STORING \
fprintf(fid,"%f\r\n",y); \
#endif
#define OUT_LOP_ITERATION y=0; \
xIndex=xCounter-HL;\
for(hCounter=HL_MINUS_1;hCounter>0;)
{LOOP_ITERATION} \
SINGLE_ITERATION
But the problem is when the MEMORIZE flag is defined. Here is the output of pre-processor created by compiler
for( xCounter=XL_MINUS_1;xCounter>=0;xCounter--)
{
y=0;
xIndex=xCounter-HL;
for(hCounter=HL_MINUS_1;hCounter>0;)
{
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
y+=xext[++xIndex]*H[hCounter--];
}
y+=xext[++xIndex]*H[hCounter--];
#ifdef
myOutput[xCounter]=y;
#endif
#ifdef STORING
fprintf(fid,"%f\r\n",y);
#endif
}
which has a problem in the last part.in the :
#ifdef
myOutput[xCounter]=y;
#endif
#ifdef STORING
fprintf(fid,"%f\r\n",y);
#endif
}
which must be
#ifdef MEMORIZE
myOutput[xCounter]=y;
#endif
#ifdef STORING
fprintf(fid,"%f\r\n",y);
#endif
}
and the pre-processor omitted the MEMORIZE because it is defined currently.
Please help me to solve it.
You probably wanted:
#ifdef MEMORIZE
#define DEBUG_CODE myOutput[xCounter]=y;
#endif
#ifdef STORING
#define DEBUG_CODE fprintf(fid,"%f\r\n",y);
#endif
You may try this:
#if defined(MEMORIZE) && defined(STORING)
#define DEBUG_CODE myOutput[xCounter]=y;\
fprintf(fid,"%f\r\n",y);
#elif defined(MEMORIZE)
#define DEBUG_CODE myOutput[xCounter]=y;
#elif defined(STORING)
#define DEBUG_CODE fprintf(fid,"%f\r\n",y);
#else
#define DEBUG_CODE
#endif
Related
C++20 added std::source_location as a replacement for the debugging macros __LINE__, __FILE__, etc.
This is great. I have a macro that builds up a variable declaration in order to log and profile a block of code using said macros:
#define TOKEN_PASTE_SIMPLE(x, y) x##y
#define TOKEN_PASTE(x, y) TOKEN_PASTE_SIMPLE(x, y)
#define TOKEN_STRINGIZE_SIMPLE(x) #x
#define TOKEN_STRINGIZE(x) TOKEN_STRINGIZE_SIMPLE(x)
//...
#if defined PROFILE_LOG_SCOPE || defined PROFILE_LOG_SCOPE_FUNCTION
#undef PROFILE_LOG_SCOPE
#undef PROFILE_LOG_SCOPE_FUNCTION
#endif
#ifdef PROFILE_BUILD
#define PROFILE_LOG_SCOPE(tag_str) ProfileLogScope TOKEN_PASTE(plscope_, __LINE__)(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION() PROFILE_LOG_SCOPE(__FUNCSIG__)
#else
#define PROFILE_LOG_SCOPE(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION()
#endif
However, replacing the macros with the source_location version breaks because the function calls are not evaluated before the macro expansion.
#define TOKEN_PASTE_SIMPLE(x, y) x##y
#define TOKEN_PASTE(x, y) TOKEN_PASTE_SIMPLE(x, y)
#define TOKEN_STRINGIZE_SIMPLE(x) #x
#define TOKEN_STRINGIZE(x) TOKEN_STRINGIZE_SIMPLE(x)
//...
//TODO: Replace __LINE__ with std::source_location::line
//TODO: Replace __FUNCSIG__ with std::source_location::function_name
#if defined PROFILE_LOG_SCOPE || defined PROFILE_LOG_SCOPE_FUNCTION
#undef PROFILE_LOG_SCOPE
#undef PROFILE_LOG_SCOPE_FUNCTION
#endif
#ifdef PROFILE_BUILD
#define PROFILE_LOG_SCOPE(tag_str) ProfileLogScope TOKEN_PASTE(plscope_, std::source_location::current().line())(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION() PROFILE_LOG_SCOPE(std::source_location::current().function_name())
#else
#define PROFILE_LOG_SCOPE(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION()
#endif
QUESTION
How would I get the above to work?
I ultimately went with a hybrid approach. That is, Use __LINE__ to generate the variable name and pass in std::source_location::current() as a default parameter:
//...
class ProfileLogScope {
public:
explicit ProfileLogScope(const char* scopeName = nullptr, std::source_location location = std::source_location::current()) noexcept;
//...
};
ProfileLogScope::ProfileLogScope(const char* scopeName, std::source_location location) noexcept
: m_scope_name(scopeName)
, m_time_at_creation(TimeUtils::Now())
, m_location(location)
{
/* DO NOTHING */
}
ProfileLogScope::~ProfileLogScope() noexcept {
const auto now = TimeUtils::Now();
TimeUtils::FPMilliseconds elapsedTime = (now - m_time_at_creation);
DebuggerPrintf(std::format("ProfileLogScope {} in file {} on line {} took {:.2f} milliseconds.\n", m_scope_name != nullptr ? m_scope_name : m_location.function_name(), m_location.file_name(), m_location.line(), elapsedTime.count()));
}
//...
#define TOKEN_PASTE_SIMPLE(x, y) x##y
#define TOKEN_PASTE(x, y) TOKEN_PASTE_SIMPLE(x, y)
#define TOKEN_STRINGIZE_SIMPLE(x) #x
#define TOKEN_STRINGIZE(x) TOKEN_STRINGIZE_SIMPLE(x)
//...
#if defined PROFILE_LOG_SCOPE || defined PROFILE_LOG_SCOPE_FUNCTION
#undef PROFILE_LOG_SCOPE
#undef PROFILE_LOG_SCOPE_FUNCTION
#endif
#ifdef PROFILE_BUILD
#define PROFILE_LOG_SCOPE(tag_str) auto TOKEN_PASTE(plscope_, __LINE__) = ProfileLogScope{tag_str}
#define PROFILE_LOG_SCOPE_FUNCTION() auto TOKEN_PASTE(plscope_, __LINE__) = ProfileLogScope{nullptr}
#else
#define PROFILE_LOG_SCOPE(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION()
#endif
How can I define a nested #define into a macro with variadic arguments
#ifndef MY_PRINTF
#define MY_PRINTF(f_, ...) { \
#ifdef USE_WRITE_DEBUG_INFO \
char buff[200]; \
sprintf(buff, (f_), __VA_ARGS__); \
WriteDebugInfo(buff); \
#else \
printf((f_), __VA_ARGS__); \
#endif \
}
#endif
Visual studio complains about missing directives. I'd appreciate for any hint.
You can't use preprocessor directives while defining a #define. This means that your #ifdef USE_WRITE_DEBUG_INFO won't work.
For this case, use a function rather than a macro:
#include <cstdarg>
void my_printf(const char* format, ...) {
#ifdef USE_WRITE_DEBUG_INFO
char buff[200];
va_list args;
va_start(args, format);
// Note: uses the snprintf variant rather than sprintf variant,
// avoiding buffer overlows.
vsnprintf(buff, 200, format, args);
va_end(args);
WriteDebugInfo(buff);
#else
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
#endif
}
In general, you'd have to bring the preprocessor directives outside of the #define:
#ifndef MY_PRINTF
#ifdef USE_WRITE_DEBUG_INFO
// do { ... } while (false) makes the macro behave mostly like a regular function call.
#define MY_PRINTF(f_, ...) do { \
char buff[200]; \
sprintf(buff, (f_), __VA_ARGS__); \
WriteDebugInfo(buff); \
} while (false)
#else
#define MY_PRINTF(f_, ...) printf((f_), __VA_ARGS__)
#endif
#endif
I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC.
The gcc way is quite straight using the __attribute__ keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things.
Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)
Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void finalize(void)
{
printf( "finalize\n");
}
INITIALIZER( initialize)
{
printf( "initialize\n");
atexit( finalize);
}
int main( int argc, char** argv)
{
printf( "main\n");
return 0;
}
You are probably interested in DllMain.
I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)
Untested, but this should at least allow the same code to work in both MSVC and GCC.
#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
void fn(void) __attribute__((constructor))
#endif
static constructor(foo);
void foo() {
...
}
I tried the last answer in MSVC like
#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that
#ifdef _MSC_VER
#define INITIALIZER(f) \
static void f();\
static int __f1(){f();return 0;}\
__pragma(data_seg(".CRT$XIU"))\
static int(*__f2) () = __f1;\
__pragma(data_seg())\
static void f()
#else
#define INITIALIZER(f) \
__attribute__((constructor)) static void f()
#endif
I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC.
The gcc way is quite straight using the __attribute__ keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things.
Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)
Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void finalize(void)
{
printf( "finalize\n");
}
INITIALIZER( initialize)
{
printf( "initialize\n");
atexit( finalize);
}
int main( int argc, char** argv)
{
printf( "main\n");
return 0;
}
You are probably interested in DllMain.
I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)
Untested, but this should at least allow the same code to work in both MSVC and GCC.
#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
void fn(void) __attribute__((constructor))
#endif
static constructor(foo);
void foo() {
...
}
I tried the last answer in MSVC like
#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that
#ifdef _MSC_VER
#define INITIALIZER(f) \
static void f();\
static int __f1(){f();return 0;}\
__pragma(data_seg(".CRT$XIU"))\
static int(*__f2) () = __f1;\
__pragma(data_seg())\
static void f()
#else
#define INITIALIZER(f) \
__attribute__((constructor)) static void f()
#endif
When building application for x86, the following code works fine:
#if defined _WIN32
#define LIB_PRE __declspec(dllexport)
#elif defined __unix__
#define LIB_PRE
#else
#define LIB_PRE __declspec(dllexport)
#endif
But gives an error for GCC (ARM). I have found out that __declspec(dllexport) wont work on GCC. If so, what should I use for GCC (ARM)?
Edit:
Its used in many classes. e.g:
class CJsonValueString : public CJsonValue
{
private:
jstring value;
public:
LIB_PRE CJsonValueString(jstring value);
LIB_PRE CJsonValueString(const CJsonValueString * value);
LIB_PRE jstring ToString() const;
LIB_PRE int ToInt() const;
LIB_PRE int64 ToInt64 () const;
LIB_PRE float ToFloat () const;
LIB_PRE void GetValue(jstring & str) const;
};
Basically, you probably don't need anything special. But if you want (and if working on shared objects, i.e. *.so files), learn more about visibility pragmas and visibility function attributes
And the question is more target operating system specific than target machine specific. (I would imagine that an ARM running some obscure Windows8/ARM system would also need your __declspec; conversely, your __declspec has no sense on Linux/x86).
Here's a simplified version of what we use in our code.
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
#if defined(__NT__) // MS Windows
#define idaapi __stdcall
#define ida_export idaapi
#if defined(__IDP__) // modules
#define idaman EXTERNC
#else // kernel
#if defined(__X64__) || defined(__NOEXPORT__)
#define idaman EXTERNC
#else
#define idaman EXTERNC __declspec(dllexport)
#endif
#endif
#define ida_local
#elif defined(__UNIX__) // for unix
#define idaapi
#if defined(__MAC__)
#define idaman EXTERNC __attribute__((visibility("default")))
#define ida_local __attribute__((visibility("hidden")))
#else // Linux
#if __GNUC__ >= 4
#define idaman EXTERNC __attribute__ ((visibility("default")))
#define ida_local __attribute__((visibility("hidden")))
#else
#define idaman EXTERNC
#define ida_local
#endif
#endif
#endif
On Linux/OS X, we compile all code by default with -fvisibility=hidden -fvisibility-inlines-hidden and mark up stuff we want to export with idaman, e.g.
idaman bool ida_export set_enum_width(enum_t id, int width);
Since you're exporting C++ methods, you'll probably want to skip the extern "C" part.