假设我正在围绕 ExpandEnvironmentStringsW 实现一个简单的包装器:
//ExpandNStuff.hpp:
#include <string>
namespace WindowsApi
{
std::wstring ExpandEnvironmentStrings(const std::wstring& source);
}
//ExpandNStuff.cpp:
#include <windows.h>
#include "ExpandNStuff.hpp"
#include "Win32Exception.hpp"
namespace WindowsApi
{
std::wstring ExpandEnvironmentStrings(const std::wstring& source)
{
DWORD len;
std::wstring result;
len = ::ExpandEnvironmentStringsW(source.c_str(), 0, 0);
if (len == 0)
{
THROW_LAST_WINDOWS_ERROR();
}
result.resize(len);
len = ::ExpandEnvironmentStringsW(source.c_str(), &result[0], len);
if (len == 0)
{
THROW_LAST_WINDOWS_ERROR();
}
result.pop_back(); //Get rid of extra null
return result;
}
}
没什么大不了的——到目前为止一切都有意义。看看什么时候会发生
我添加 main.cpp
:
#include <iostream>
#include <string>
#include "ExpandNStuff.hpp"
int main()
{
std::wstring source(L"Hello World! Windows is in %WINDIR%");
std::wstring expanded(WindowsApi::ExpandEnvironmentStrings(source));
std::wcout << expanded << std::endl;
}
惊喜!此代码不会链接。原因是在ExpandNStuff.cpp
翻译单位windows.h
header 已定义 ExpandEnvironmentStrings
到
是ExpandEnvironmentStringsW
使用宏,尽管我们尝试过
通过将其放入命名空间来使我们的实现与众不同。所以
ExpandNStuff.cpp
翻译单元认为函数被调用
WindowsApi::ExpandEnvironmentStringsW
而不是
WindowsApi::ExpandEnvironmentStrings
,如作者所料。但是 main.cpp
翻译单位不#include <windows.h>
,因此它的名称与 ExpandNStuff.cpp
中的名称不匹配翻译单元。
修复方法是将其添加到 ExpandNStuff.hpp
中:
#ifdef ExpandEnvironmentStrings
#undef ExpandEnvironmentStrings
#endif
但是,为每个 API 执行此操作可能会很乏味。我宁愿只是被迫显式调用函数的“W”或“A”版本,也不愿被 #define
咬住。像这样的错误。有没有办法关闭宏?
最佳答案
它们的定义没有包含在任何宏中。
WINBASEAPI
BOOL
WINAPI
GetVolumeInformationA(
__in_opt LPCSTR lpRootPathName,
__out_ecount_opt(nVolumeNameSize) LPSTR lpVolumeNameBuffer,
__in DWORD nVolumeNameSize,
__out_opt LPDWORD lpVolumeSerialNumber,
__out_opt LPDWORD lpMaximumComponentLength,
__out_opt LPDWORD lpFileSystemFlags,
__out_ecount_opt(nFileSystemNameSize) LPSTR lpFileSystemNameBuffer,
__in DWORD nFileSystemNameSize
);
WINBASEAPI
BOOL
WINAPI
GetVolumeInformationW(
__in_opt LPCWSTR lpRootPathName,
__out_ecount_opt(nVolumeNameSize) LPWSTR lpVolumeNameBuffer,
__in DWORD nVolumeNameSize,
__out_opt LPDWORD lpVolumeSerialNumber,
__out_opt LPDWORD lpMaximumComponentLength,
__out_opt LPDWORD lpFileSystemFlags,
__out_ecount_opt(nFileSystemNameSize) LPWSTR lpFileSystemNameBuffer,
__in DWORD nFileSystemNameSize
);
#ifdef UNICODE
#define GetVolumeInformation GetVolumeInformationW
#else
#define GetVolumeInformation GetVolumeInformationA
#endif // !UNICODE
您可以看到没有方便的开关来阻止 GetVolumeInformation 的#defining。
编辑:
Boost 有一个解决方案——BOOST_PREVENT_MACRO_SUBSTITUTION。他们将它用于 min() 和 max()。 “使用 min BOOST_PREVENT_MACRO_SUBSTITUTION (a,b); 对 min(a,b) 进行参数依赖调用。”
关于c++ - Windows header 中是否有禁用 TCHAR 中性函数名称宏定义的设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4638824/