2

I have a combination of libraries that are suffering from namespace pollution due to the use of macros and macro names in function prototypes of the same name. Specifically, I am using my GUI library Eagle and my friend's networking library Nilorea.

  1. How do I obtain a list of all the function like macros included in my code? I looked at MSVS and CodeBlocks and I can't seem to find a way to list them. I can also use grep, but that is only effective on a directory or easily obtained list of files.

    I read about this (Macro and function with same name) and discovered I can (surround) a function name in a declaration to prevent macro expansion, but that only solves the instances where I am using a function with the same name as the macro. MinGW is using macro names for functions I cannot change.

    I avoided some namespace collision by separating out bad headers like windows.h and defining NOGDI to avoid some others, but I can't seem to get rid of them all.

  2. I know I can #undef a symbol if I need to and I've had limited success with this, along with changing the order of inclusion of headers, but I'm still having problems.

So what options do I have to scrub my code of these obnoxious macros?'

I looked at the CPP (C preprocessor) program's help and it doesn't show any abilities to list the macros in a given header.

Do I need to write my own custom solution? What about Clang?

For an example of the collision between Nilorea and MinGW-W64 see here :

This is a macro in Nilorea that collides with mingw :

/*! Free Handler to get errors */
#define Free( ptr ) \
    if (  ptr  )\
    {\
        free(  ptr  );\
        ptr  = NULL;\
    }\
    else\
    {\
        n_log( LOG_DEBUG , "Free( %s ) already done or NULL at line %d of %s \n", #ptr , __LINE__ , __FILE__ );\
    }

The compiler error it generates is misleading, but points to c:\mingw\i686-w64-mingw32\include\objidbase.h and oaidl.h in these function prototypes :

#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("00000002-0000-0000-c000-000000000046")
IMalloc : public IUnknown
{
    virtual void * STDMETHODCALLTYPE Alloc(
        SIZE_T cb) = 0;

    virtual void * STDMETHODCALLTYPE Realloc(
        void *pv,
        SIZE_T cb) = 0;

    virtual void STDMETHODCALLTYPE Free(
        void *pv) = 0;

    virtual SIZE_T STDMETHODCALLTYPE GetSize(
        void *pv) = 0;

    virtual int STDMETHODCALLTYPE DidAlloc(
        void *pv) = 0;

    virtual void STDMETHODCALLTYPE HeapMinimize(
        ) = 0;

};

BugSquasher
  • 335
  • 1
  • 13
  • 1
    Ultimately, the C preprocessor is a blunt weapon for mangling text and it is hard to avoid problems like this except by renaming your macros and functions. Do you use a systematic prefix on the names exposed in your GUI library? You should,. Does your friend's library use a (different) systematic prefix on the names it exposes? Again, if not, it should. – Jonathan Leffler Aug 13 '19 at 17:57
  • 1
    You should also make sure you steer clear of names reserved for the implementation. A short version of that is "names starting with an underscore"; the full rules ([C11 §7.1.3 Reserved identifiers](https://port70.net/~nsz/c/c11/n1570.html#7,1.3)) are subtler than that but you won't go amiss following the short version of the rules. – Jonathan Leffler Aug 13 '19 at 17:58
  • @JonathanLeffler My library is C++, Nilorea is C. My library collides with windows.h when both are included namely on "CreateWindow" and "Rectangle" which are both used by win32. Those I will eventually rename. And no, sadly Nilorea has no prefix on the macros it uses that collide with MinGW-W64. – BugSquasher Aug 13 '19 at 18:00
  • Time to choose different libraries? You can use namespaces in your C++ GUI library to help a bit — though macros are still a bludgeon with no knowledge of namespaces. If your code has to coexist with Windows, you'll have to stay far enough away from Windows names — they're effectively reserved for you. – Jonathan Leffler Aug 13 '19 at 18:02
  • @JonathanLeffler macros don't care about namespaces, but I will be using one in my library as soon as I get around to it. Honestly, these are the two best libraries I could be using, as they both do exactly what I need. – BugSquasher Aug 13 '19 at 18:03
  • I will edit my question to provide a specific example. – BugSquasher Aug 13 '19 at 18:05
  • @BugSquasher Is it something that *needs* to be a macro? You can do a lot with template meta-programming. – Thomas Jager Aug 13 '19 at 18:06
  • 1
    The C standard requires macros that map standard functions to be function-like macros (with a parameter list), which limits the damage they can do. If the conflicting code is using object-like macros (no parameter list), then they do make life harder. Otherwise, I'm not sure there's an easy way out. There are options in GCC to print all preprocessor definitions — see [preprocessor options](https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Preprocessor-Options.html#Preprocessor-Options) especially `-dletters` (`-dM` etc). – Jonathan Leffler Aug 13 '19 at 18:11
  • -lmacros looks very promising @JonathanLeffler – BugSquasher Aug 13 '19 at 18:14
  • The macro `Free` from the Nilaroa library obviously conflicts with the interface shown. You either need to define `CINTERFACE` or you have to rename the macro: `#define Nilaroa_Free(ptr) …` or something similar. Otherwise, you're stuck between a rock and a hard place — you have to determine what you can change, and if you can't change any of the conflicting names, then you'll have to give up either on the o/s or the Nilaroa library — it's probably easier to give up on the library. – Jonathan Leffler Aug 13 '19 at 18:15
  • @JonathanLeffler ```#define CINTERFACE``` seems to solve the problems. I can now compile an empty main while including headers for both Eagle and Nilorea. What do I lose by defining CINTERFACE? Just the C++ version of some COM functions? I can't quite tell what its for from a cursory google. – BugSquasher Aug 13 '19 at 18:23
  • I've no idea what you're losing — I'm not a Windows programmer. It isn't strictly C code that you're losing (it's C++ code, AFAICT, plus some macros), but that's probably not news to you. If you weren't aware of using it, you probably weren't. (And apologies for the typo of Nilaroa for Nilorea.) – Jonathan Leffler Aug 13 '19 at 18:44

0 Answers0