Related
I am attempting to create a C++ DLL to export, and I need to export all functions of a class. So I came up with this idea to cut out the boilerplate:
#define CONCATENATE_WRAPPED(arg1, arg2) CONCATENATE_WRAPPED_1(arg1, arg2)
#define CONCATENATE_WRAPPED_1(arg1, arg2) CONCATENATE_WRAPPED_2(arg1, arg2)
#define CONCATENATE_WRAPPED_2(arg1, arg2) CONCATENATE_WRAPPED_3(arg1, arg2)
#define CONCATENATE_WRAPPED_3(arg1, arg2) CONCATENATE_WRAPPED_4(arg1, arg2)
#define CONCATENATE_WRAPPED_4(arg1, arg2) arg1##arg2
// Counts the number of pairs:
#define PAIR_SEQUENCER(_1, _1x, _2, _2x, _3, _3x, _4, _4x, N, ...) N
#define COUNT_PAIRS(...) PAIR_SEQUENCER(__VA_ARGS__, 4, x, 3, x, 2, x, 1, 0, 0, x)
// Internal for declaring arguments:
#define DECLARE_ARGUMENTS_0(...)
#define DECLARE_ARGUMENTS_1(typeName, varName, ...)\
typeName varName
#define DECLARE_ARGUMENTS_2(typeName, varName, ...)\
typeName varName,\
DECLARE_ARGUMENTS_1(__VA_ARGS__)
#define DECLARE_ARGUMENTS_3(typeName, varName, ...)\
typeName varName,\
DECLARE_ARGUMENTS_2(__VA_ARGS__)
// Internal for passing arguments:
#define PASS_ARGUMENTS_0(...)
#define PASS_ARGUMENTS_1(typeName, varName, ...)\
varName\
PASS_ARGUMENTS_0(__VA_ARGS__)
#define PASS_ARGUMENTS_2(typeName, varName, ...)\
varName, \
PASS_ARGUMENTS_1(__VA_ARGS__)
#define PASS_ARGUMENTS_3(typeName, varName, ...)\
varName, \
PASS_ARGUMENTS_2(__VA_ARGS__)
// Macro to call when declaring parameters and will adjust depending on the number of params, so that
// DECLARE_ARGUMENTS(int, a, float, b) expands to (int a, float b) for up to three pairs.
#define DECLARE_ARGUMENTS(...) ( CONCATENATE_WRAPPED(DECLARE_ARGUMENTS_, COUNT_PAIRS(__VA_ARGS__))(__VA_ARGS__) ))
// Macro to call when passing parameters and will adjust depending on the number of params, so that
// PASS_ARGUMENTS(int, a, float, b) expands to (a, b) for up to three pairs.
#define PASS_ARGUMENTS(...) ( CONCATENATE_WRAPPED(PASS_ARGUMENTS_, COUNT_PAIRS(__VA_ARGS__))(__VA_ARGS__) )
With all this context out of the way, this is what my main macro looks like:
#define IMPLEMENT_CONSTRUCTOR(typeName, functionName, ...) \
extern "C" __declspec(dllexport) typeName* __stdcall functionName DECLARE_ARGUMENTS(__VA_ARGS__) \
{ \
return new typeName PASS_ARGUMENTS(__VA_ARGS__); \
} \
typeName::typeName DECLARE_ARGUMENTS(__VA_ARGS__)
// the intention is so that
IMPLEMENT_CONSTRUCTOR(MacroTestObject, CreateMacroTestObjectWithTwoParams, int, TwoParamFirst, float, TwoParamSecond)
{ }
//expands to
extern "C" __declspec(dllexport) MacroTestObject* __stdcall CreateMacroTestObjectWithTwoParams(int TwoParamFirst, float TwoParamSecond)
{
return new MacroTestObject(TwoParamFirst, TwoParamSecond);
}
MacroTestObject::MacroTestObject(int TwoParamFirst, float TwoParamSecond)
{ }
But the problem seems to be that the C++ compiler starts compiling even before all the macros have expanded, which throws out compile-time errors like crazy, showing something like:
0><Project>\MacroTestObject.cpp(4,1): Error C2512 : 'MacroTestObject::MacroTestObject': no appropriate default constructor available
0><Project>\MacroTestObject.cpp(5,1): Error C2511 : 'MacroTestObject::MacroTestObject(void)': overloaded member function not found in 'MacroTestObject'
But when I use (Rider for Unreal Engine)'s "Substitute macro calls and all nested calls" function, the macro expands out just fine.
Can someone help me out with this, I don't know why this is happening and I can't seem to find any particular assistance online.
This DLL is meant to be used in Unity3D as a native plug-in and so as far as I know using C++/CLI is out of the question. I don't think COM interop is an option either because all the info I read about it implies that I need to create TLB files, and since Unity handles C# compilation, that seems out of the question too.
EDIT:
I think I kind of figured out why this is causing issues.
// Something like
COUNT_PAIRS(a, b, c, d, e, f)
// always expands to
0
// because __VA_ARGS__ is considered as a single argument
// and a recount is not triggered. I tried using CONCATENATE_WRAPPED
// in different places but unfortunately it has been no help.
Could someone help me out with this?
Edit 2:
Solved the problem, switched to Clang. Also, there's an extra bracket in DECLARE_ARGUMENTS macro.
So I think this version should now work as you would want.
I've found two problems:
The already mentioned additional ")" in DECLARE_ARGUMENT, that was an easy fix
The fact that MSVC seems to trat __VA_ARGS__ differently than gcc and clang, it doesn't expand the arguments into themselves but treats it one. That's why e.g. COUNT_PAIRS didn't work correctly. The fix is taken from this SO Question
I suggest playing around with it a bit in godbolt to see how it works ;)
Hope this solves your problem
EDIT: I also just saw here that Visual Studio has apparently updated their preprocessor, so depending on which version one is using it could be possible to avoid all the ugly EXPAND calls by using the compiler switch /Zc:preprocessor
I'm adding a macro used in C file which should take a variable number of arguments, which should be handled based on the type and the number of arguments differently. If it's pure C++, it's easily achieved by overloading the function, but how would I pass the variadic arguments from C macro into C++ with this mixture of C and C++?
The C file is restricted to be compiled with gcc. In macro definition, I passed the variadic arguments into C wrapper function. Since the number of arguments is unknown, I have a macro counting the arguments and pass it along into va_list. But using this approach, I do not know the type of arguments to flexibly pass any arguments to C++ function. I'm including relevant code snippet reflecting the current structure of code, skipping the actual handling logic in cpp file and other irrelevant information.
In use.c:
#include "macro.h"
LOG(id, lvl, params);
In macro.h:
#define LOG(_MSG_ID_, _LOG_LVL_, ...) \
log_data(&hdr, ##__VA_ARGS__); \
In logger.h:
#define GET_NARG(_1, _2, _3, _4, N, ...) N
#define COUNT_VARARGS(...) GET_NARG(__VA_ARGS__, 4, 3, 2, 1)
#define log_data(p_hdr, ...) \
log_data_c(p_hdr, COUNT_VARARGS(__VA_ARGS__), ##__VA_ARGS__);
#ifdef __cplusplus
class LOGGER
{
public:
void log_data(LOG_HEADER_s* hdr);
void log_data(LOG_HEADER_s* hdr, uint16_t val);
void log_data(LOG_HEADER_s* hdr, uint64_t val);
void log_data(LOG_HEADER_s* hdr, uint32_t val1, uint32_t val1);
// and other overloaded functions
static inline LOGGER& getInstance() { return m_instance; }
private:
static LOGGER m_instance;
};
#else
typedef struct LOGGER LOGGER;
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern void log_data_c(LOG_HEADER_s* hdr, int n, ...);
#ifdef __cplusplus
}
#endif
In logger.cpp:
#include "logger.h"
#include <stdarg.h>
LOGGER LOGGER::m_instance = LOGGER();
#define LOGGER_Instance LOGGER::getInstance()
#ifdef __cplusplus
extern "C" {
#endif
void log_cmn_data(LOG_HEADER_s* hdr, int n, ...)
{
va_list args;
va_start(args, n);
LOGGER_Instance.log_data(va_arg(args, LOG_HEADER_s*));
va_end(args);
}
#ifdef __cplusplus
}
#endif
The ideal scenario would be just passing the variadic arguments in the macro into the invocation of C++ overloaded function. Any workarounds to achieve the result are welcome. I've been trying to get this working for a while but I haven't found a post dealing with the same scenario. Any help is appreciated.
Since the number of arguments is unknown, I have a macro counting the
arguments and pass it along into va_list. But using this approach, I
do not know the type of arguments to flexibly pass any arguments to
C++ function.
That's right, you don't know. The C mechanism for variadic functions does not directly provide the called function any information about the number or types of the variable arguments. The called function must use a combination of assumptions and information gleaned from its arguments to make that determination. The printf function is the canonical example: it determines both the number of variable arguments and their types by analyzing the the provided format string (and havoc ensues if the arguments actually provided are mismatched with the format).
Provided that you place a fixed, artificial upper limit on the number of variable arguments supported, you can indeed count them via a variadic macro, as demonstrated. Very little type information is available to the preprocessor, however, and there is no applicable mechanism for applying what little such information there is to your purpose.
The usual C alternative to function overloading is simply to write functions with different names. If you have similar functions that differ primarily in parameter number and type, then you might give them related names that convey those types. For example,
void log_data(LOG_HEADER_s *);
void log_data_u16(LOG_HEADER_s* hdr, uint16_t);
void log_data_u64(LOG_HEADER_s* hdr, uint64_t);
void log_data_u32_u32(LOG_HEADER_s* hdr, uint32_t, uint32_t);
Alternatively, it might be more appropriate to give them names that convey the purpose of their particular signature. I'm inclined to suspect that an approach along these lines would work better for you than trying to multiplex your several distinct logging functions through a single variadic interface.
On the other hand, if you insist on providing a single variadic function interface, then you could put multiple for-purpose macros in front of it on the C side, each corresponding to one of the supported back-end signatures. These would not need to be variadic (unless the corresponding specific function was). This would be to your advantage because you would get at least argument-count validation from your compiler (for calls going through the macros), and they could provide whatever extra arguments are needed to convey the expected number and types of arguments to the variadic interface function.
Please refer this FASTLZ.C source code.
At Line #113 and #128 it's including its own source file.
I think it's intention was two defined following functions names with respect to their FASTLZ_LEVEL macro value.
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
and
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
But I cannot figure it out the theory or key feature behind this Macro in C language, please can someone briefly explain this scenario?
This defines two pairs of functions called fastlz1_compress and fastlz1_decompress, and fastlz2_compress and fastlz2_decompress. The two compress functions are very similar except for a few lines here and there, and similarly for the decompress functions. The self inclusion, which happens twice, is done to remove repetition in the definitions of these two pairs of functions.
Here's an abbreviated version of what the file contains:
#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
...
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 1
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 2
#undef MAX_DISTANCE
#define MAX_DISTANCE 8191
#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
...
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
...
#if FASTLZ_LEVEL==2
...
#endif
...
#if FASTLZ_LEVEL==1
...
#else
...
#endif
...
}
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
{
...
#if FASTLZ_LEVEL==2
...
#endif
...
#if FASTLZ_LEVEL==1
...
#else
...
#endif
...
}
#endif
The first part of the file containing the #if block contains a series of macro definitions, but you'll notice that they're defined twice. The second part of the file containing the #else block basically contains a pair of function templates.
The first part defines some macros, then includes itself. On the self-inclusion, the #else part takes effect. This defines fastlz1_compress and fastlz1_decompress based on the FASTLZ_COMPRESSOR and FASTLZ_DECOMPRESSOR macros. Because FASTLZ_LEVEL is set to 1, this activates the fastlz1_compress and fastlz1_decompress specific code.
After the first self-include, these macros are undefined and then redefined for fastlz2_compress and fastlz2_decompress, then the file is self-included again. So the #else part is pulled in again, but this time the effect is fastlz2_compress and fastlz2_decompress are defined, and the code specific to these functions is activated by virtue of FASTLZ_LEVEL now being set to 2.
A slightly less confusing way to do this would have been to put everything between the outer #if and #else in one file and the part between #else and #endif in another file.
A better way would have been to create a single compress function and a single decompress function, with each accepting a parameter to specify the level rather than using macro trickery. For example:
static FASTLZ_INLINE int fastlz_compress(const void* input, int length, void* output, int level)
{
...
if (level==2) {
...
}
...
if (level==1) {
...
} else {
...
}
...
}
Used properly, this can be a useful technique.
Say you have a complex, performance critical subsystem with a fairly small public interface and a lot of non-reusable implementation code. The code runs to several thousand lines, a hundred or so private functions and quite a bit of private data. If you work with non-trivial embedded systems, you probably deal with this situation frequently enough.
Your solution will probably be layered, modular and decoupled and these aspects can be usefully represented and reinforced by coding different parts of the subsystem in different files.
With C, you can lose a lot by doing this. Almost all toolchains provide decent optimisation for a single compilation unit, but are very pessimistic about anything declared extern.
If you put everything into one C source module, you get -
Performance & code size improvements - function calls will be inlined in many cases. Even without inlining, the compiler has opportunities to produce more efficient code.
Link level data & function hiding.
Avoidance of namespace pollution and its corollary - you can use less unwieldy names.
Faster compilation & linkage.
But you also get an unholy mess when it comes to editing this file and you lose the implied modularity. This can be overcome by splitting the source into several files and including these to produce a single compilation unit.
You need to impose some conventions to manage this properly though. These will depend on your toolchain to some extent, but some general pointers are -
Put the public interface in a separate header file - you should be doing this anyway.
Have one main .c file that includes all the subsidiary .c files. This
could also include the code for the public interface.
Use compiler guards to ensure that private headers and source modules
are not included by external compilation units.
All private data & functions should be declared static.
Maintain the conceptual distinction between .c and .h files. This
leverages existing conventions. The difference is that you will have
a lot of static declarations in your headers.
If your toolchain doesn't impose any reason not to, name the private
implementation files as .c and .h. If you use include guards, these
will produce no code and introduce no new names (you may end up with
some empty segments during linkage). The huge advantage is that other
tools (e.g. IDEs) will treat these files appropriately.
In line 27:
#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
you have conditional preprocessor directive, which in line 164 starts it's "else" part, which ends at the end of file. This splits file into two parts: main declaration of general fastlz functions, which is parsed once by compiler, and second part which contains implementation of two functions (FASTLZ_COMPRESSOR and FASTLZ_DECOMPRESSOR).
These two function implementations, which names happen to be a macro definitions, are included twice by first part of file, with some parameters declared (their final names and some other) as macro definitions shortly before inclusion.
This is the C-way of keeping code DRY and don't repeat two almost identical implementations. In C++ (since you've added a C++ tag), you have other mechanisms for the same purpose: inheritance, templates, templates specializations, if constexpr etc.
BTW: mentioned before first if-def line probably contains a bug - it checks if any of the definition was defined, but name of first one "FASTLZ__COMPRESSOR" contains '__' rather than '_' used later. This code fortunately works well, because checked defines are always defined together : ).
I am using some standard libraries to develop a general interface for some devices.
In some part of code I have
//header.h
#ifndef _M_X64
# define GC_CALLTYPE __stdcall
#else
# define GC_CALLTYPE /* default */ //this is my case
#endif
...
typedef int32_t GC_ERROR;
...
/* typedefs for dynamic loading */
#define GC_API_P(function) typedef GC_ERROR( GC_CALLTYPE *function )
GC_API_P(PTLOpen)( TL_HANDLE *phTL );
and in my source files I have
//source1.cpp
TLOpen(&hTl)
//source2.cpp
#define FUNCTION_POINTER(function, ptype, hModule) \
((function) = reinterpret_cast<ptype>(GetProcAddress((hModule), #function))) // What is this #?
GC::PTLOpen TLOpen = 0;
FUNCTION_POINTER(TLOpen, GC::PTLOpen, hModule);
I want to find out:
What is the TLopen() declaration? I replaced macros and got this:
typedef int32_t( GC_CALLTYPE *PTLOpen )( TL_HANDLE *phTL );
But I have learned function pointers differently and I expected something like this:
typedef int32_t( *PTLOpen )( TL_HANDLE *phTL );
Is the above declaration still a function pointer one? What about GC_CALLTYPE?
What is that # sign before function in defining FUNCTION_POINTER macro?
Where is the body of TLopen() function? I have some .lib and .dll files to be included. May the body exist in those files in compiled form?
GC_CALLTYPE is in a place where a calling convention specifier can be (like __stdcall). Can be because don't forget that very easily GC_CALLTYPE can also expand to an empty string. A quick search gave a question where this syntax is discussed here in SO: How to declare an __stdcall function pointer
This is called stringification: for example #function will expand to "xyz" if the corresponding macro argument was xyz. More here.
Yes, it can, in either actually. Your API will tell you how to do the compilation so that the program can find the function. This is the whole purpose of having libraries and a linker.
Is it possible to do something like this
#ifdef SOMETHING
#define foo //
#else
#define foo MyFunction
#endif
The idea is that if SOMETHING is defined, then calls to foo(...) become comments (or something that doesn't get evaluated or compiled), otherwise it becomes a call to MyFunction.
I've seen __noop used, but I don't believe I can use that.
EDIT(s):
I don't think I can really use a macro here, because MyFunction takes a variable number of arguments.
Also, I'd like to make it so the arguments are NOT evaluated! (So doing something like commenting out the body of MyFunction doesn't really give me what I need, as the arguments will still be evaluated)
Try this:
#ifdef SOMETHING
#define foo(x)
#else
#define foo(x) MyFunction(x)
#endif
If your function has several arguments, then:
#ifdef SOMETHING
#define foo(x,y,z)
#else
#define foo(x,y,z) MyFunction(x,y,z)
#endif
If your function has a variable number of arguments, then your compiler may support so-called "variadic macros", like this:
#ifdef SOMETHING
#define foo(...)
#else
#define foo(...) MyFunction(__VA_ARGS__)
#endif
The reason which I've seen this kind of thing used in practice is to get rid of logging functions from a release build. However, see also Separate 'debug' and 'release' builds? in which people question whether you should even have different builds.
Alternatively, instead of redefining the function call as nothing, Jonathan's comment to this answer suggested doing something like the following:
#ifdef SOMETHING
#define foo(...) do { if (false) MyFunction(__VA_ARGS__) } while (0)
#else
#define foo(...) do { if (true) MyFunction(__VA_ARGS__) } while (0)
#endif
The reasoning for doing this is so that the function call is always compiled (so it won't be left with gratuitous errors like references to deleted variables), but only called when needed: see Kernighan & Pike The Practice of Programming and also the Goddard Space Flight Center programming standards.
From a debug.h file (originating from 1990, and therefore not using __VA_ARGS__):
/*
** Usage: TRACE((level, fmt, ...))
** "level" is the debugging level which must be operational for the output
** to appear. "fmt" is a printf format string. "..." is whatever extra
** arguments fmt requires (possibly nothing).
** The non-debug macro means that the code is validated but never called.
** -- See chapter 8 of 'The Practice of Programming', by Kernighan and Pike.
*/
#ifdef DEBUG
#define TRACE(x) db_print x
#else
#define TRACE(x) do { if (0) db_print x; } while (0)
#endif /* DEBUG */
With C99, there's no longer a need for the double parentheses trick. New code should not use it unless C89 compatibility is an issue.
Maybe an easier way to do this would be to conditionally omit the body of the function?
void MyFunction() {
#ifndef SOMETHING
<body of function>
#endif
}
Unless you specifically don't want a function call to be made at all, this seems like a clean way to achieve your goal.
Unfortunately the current C++ version doesn't support variadic macros.
However, you can do this:
#ifdef SOMETHING
#define foo
#else
#define foo(args) MyFunction args
#endif
// you call it with double parens:
foo((a, b, c));
If, in the case you don't want foo called, you define it as:
void foo() {}
any calls to foo() should be optimized way.
What about something along these lines:
#ifdef NDEBUG
#define DEBUG(STATEMENT) ((void)0)
#else
#define DEBUG(STATEMENT) (STATEMENT)
#endif
You would use it like this to log debugging messages:
DEBUG(puts("compile with -DNDEBUG and I'm gone"));
A non-generic version for formatted output with additional debugging information using C99 variadic macros and the __func__ identifier could look like this:
#ifdef NDEBUG
#define Dprintf(FORMAT, ...) ((void)0)
#define Dputs(MSG) ((void)0)
#else
#define Dprintf(FORMAT, ...) \
fprintf(stderr, "%s() in %s, line %i: " FORMAT "\n", \
__func__, __FILE__, __LINE__, __VA_ARGS__)
#define Dputs(MSG) Dprintf("%s", MSG)
#endif
Here's how you'd use these macros:
Dprintf("count = %i", count);
Dputs("checkpoint passed");
Likely, you don't want to do the simple "code removal" as suggested,
because your callers will be expecting the side effects of the
arguments to happen. Here are some troublesome caller snippets that
should get you thinking:
// pre/post increment inside method call:
MyFunction(i++);
// Function call (with side effects) used as method argument:
MyFunction( StoreNewUsernameIntoDatabase(username) );
If you were to disable MyFunction by simply saying:
#define MyFunction(x)
then the side effects that the callers were expecting would go away,
and their code would break, and be quite difficult to debug. I like
the "sizeof" suggestion above, and I also like the suggestion to just
disable the body of MyFunction() via #ifdef's, although that means
that all callers get the same version of MyFunction(). From your
problem statement, I presume that's not actually what you want.
If you really need to disable MyFunction() via preprocessor defines on
a per-source-file basis, then I'd do it like this:
#ifdef SOMETHING
#define MyFunction(x) NoOp_MyFunction(x)
int NoOp_MyFunction(x) { }
#endif
You could even include the implementation of NoOp_MyFunction() inside
the source & headers for MyFunction(). You also have the flexibility
to add extra logging or debugging information in NoOp_MyFunction() as
well.
No, the C and C++ Standards say you cannot #define something to be a comment, so
#define foo //
won't work.
#ifdef SOMETHING
#define foo sizeof
#else
#define foo MyFunction
#endif
I'm assuming that foo is a printf style function? Anyways, this won't work with a zero parameter function, but if that were the case, you would already know what to do. If you really want to be anal you can use (void)sizeof but that's probably unnecessary.
I'm a little reluctant to post this answer because it's use of macro hackery can become the source of problems. However - if the calls to the function you want to have disappear are always used alone in a statement (ie., they are never part of a larger expression), then something like the following could work (and it handles varargs):
#ifdef SOMETHING
#define foo (1) ? ((void) 0) : (void)
#else
#define foo MyFunction
#endif
So if you have the line of code:
foo( "this is a %s - a++ is %d\n", "test", a++);
it will end up after the preprocessing step as either:
MyFunction( "this is a %s - a++ is %d\n", "test", a++);
or
(1) ? ((void) 0) : (void)( "this is a %s - a++ is %d\n", "test", a++);
which turns the pseudo-function's parameter list into a bunch of expressions separated by the comma operator that will never be evaluated, since the conditional always returns the ((void) 0) result.
A variant of this is something close to what ChriSW and Jonathan Leffler suggested:
#ifdef SOMETHING
#define foo if (0) MyFunction
#else
#define foo if (1) MyFunction
#endif
This is slightly different in that it does not require the compiler to support variadic macros (__VA_ARGS__).
I think this can be useful for eliminating debug trace function calls which are generally never combined into a larger expression, but beyond that I think it's a dangerous technique.
Note the potential for problems - especially if the parameters in the call produce side-effects (this is a general problem with macros - not just this hack). In the example, the a++ will be evaluated only if SOMETHING is defined in the build, otherwise it's not. So if code after the call depends on the value of a to be incremented, one of the builds has a bug.
If I remember correctly, you should be able to #define your macro to "nothing" and that will cause the compiler to ignore that call
#define foo()
foo(); // this will be ignored
What about surrounding each call to myFunction with
#ifdef SOMETHING
myFunction(...);
#endif
?