9

为了整洁,我#undef想要windows.h.

例如:

namespace os_stuff
{
    #include <windows.h>

    // ARGH! Macros everywhere!

    // at least I can keep the rest of the API in here
}

// include a bunch of files here that use the Windows API through os_stuff

namespace os_stuff
{
    #include <unwindows.h> // <- #undefs all that was #defined in windows.h
}

// All clean, as though windows.h was never here. Though os_stuff, used nowhere else,
// still has all of the API declarations in it (which is OK).
4

1 回答 1

3

与其取消定义一切,不如避免一开始就定义它们。您可以通过将模块的第一部分(作为单独的源文件)显式传递给预处理器并在模块的主源文件中包含预处理器输出而不是原始源代码来实现此目的。

我使用 Visual Studio 2010 进行了尝试。在我的试用中,我创建了三个源文件。这是 headers.cpp,类似于示例代码的第一部分:

namespace os_stuff
{
#undef _MSC_EXTENSIONS
#define _WIN32_WINNT 0x0601
#include <windows.h>
}

#include "xyzzy.h"

#undef _MSC_EXTENSIONS是为了防止包含sourceannotations.h,因为从命名空间中包含该文件时会生成错误。

这是 xyzzy.h,用于从您的示例代码中演示“在此处包含一堆文件”:

os_stuff::DWORD myFunction(os_stuff::HANDLE h);

这是 test.cpp,类似于示例代码的“全部干净”部分:

#include "headers.h"

int main(int argc, char ** argv)
{
  os_stuff::DWORD UNALIGNED;
  os_stuff::HANDLE h = 0;
  UNALIGNED = myFunction(h);
  return UNALIGNED;
}

请注意,我们使用 UNALIGNED 作为变量名,不是因为它有意义,而是作为一个示例,如果您windows.h直接包含将无法使用(因为它扩展为 __unaligned 关键字)。

在 Visual Studio 2010 命令行中,headers.h像这样创建:

cl /P headers.cpp /Fiheaders.h

/P 选项在此处记录

然后你可以test.cpp用通常的方式编译:

cl test.cpp

(显然在这种情况下程序不会链接,因为我们还没有定义 myFunction,但它编译得非常愉快。)

headers.h稍微摆弄一下,自动化构建而不是从命令行进行构建应该不会太难。

在某些 C++ 编译器中,预处理器实际上是一个单独的可执行文件(这是传统模型),但如果不是这样,仍然应该有一个选项来运行预处理器而不调用编译器。

于 2012-07-15T02:53:42.590 回答