0

I have an Unreal Engine 4 project with several plugins. On of these plugins contains a FileHelper class with a method CreateFile. This has worked fine for months, but in a recent commit, a different plugin added a call to FileHelper::CreateFile and now sometimes I get a linker error saying that CreateFileW is not a member of FileHelper (this doesn't appear in every build, which I cannot yet explain). I went on to undefine CreateFile temporarily like this

#include "UtilPlugin/File/FileSystemHelper.h"

#ifdef _WIN32
#pragma push_macro("CreateFile")
#undef CreateFile
#endif //_WIN32

...//new code including CreateFile call

#ifdef _WIN32
#pragma pop_macro("CreateFile")
#endif //_WIN32

but now I get errors

C2039 'CreateFile': is not a member of 'FileSystemHelper'

C3861 'CreateFile': identifier not found

Since I know CreateFile is successfully called in other places (at least within the same plugin as the FileSystemHelper), I know that it exists.

Thus my question is, if the undefine can affect member functions like this. I have moved the #undef part above the includes in code and I don't get an error anymore, but since it occurred seemingly randomly, I'm not entirely sure that I really fixed the problem.

Tare
  • 482
  • 1
  • 9
  • 25
  • `#undef` is a preprocessor directive. The preprocessor modifies the code (e.g. source file inclusion or macro expansion) and the compiler compiles the modified code, not the original code. – paxbun Aug 27 '21 at 07:32
  • 2
    Presumably the macro was defined when the `CreateFile` function was defined causing the definition to actually be for `CreateFileW` or `CreateFileA` – Alan Birtles Aug 27 '21 at 07:40
  • I'm not sure I fully understand. Wouldn't that mean `#undef` affects the member regardless of whether it is put before or after the include in the code? – Tare Aug 27 '21 at 07:40

1 Answers1

1

Following shows a problematic case:

#define CreateFile CreateFileW

struct S
{
    void CreateFile(); // Actually void CreateFileW();
};

And then

#undef CreateFile

void foo()
{
   S s;
   s.CreateFile(); // Error, "expect" s.CreateFileW()
}

As #define might modify meaning of code (locally), #undef "cancels" that modification locally too.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • so since the define is from some windows or unreal header and I can't simply remove it, the correct way would be do undefine it in the file with (in your example) `struct S{...}` ? – Tare Aug 27 '21 at 11:39
  • "correct" way is mostly a workaround to avoid that the MACRO leaks to some other parts of the code :-/. Renaming your `CreateFile` would also fix the issue, or ensure that the MACRO is defined everywhere might also be an option. – Jarod42 Aug 27 '21 at 12:35