假设我在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头使用宏将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 bug咬到。有没有办法关闭宏?
发布于 2011-01-09 19:23:09
它们的定义没有包装在任何宏中。
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。
编辑:
Boost有一个解决方案-- BOOST_PREVENT_MACRO_SUBSTITUTION。他们将它用于min()和max()。“使用min BOOST_PREVENT_MACRO_SUBSTITUTION (a,b);对min(a,b)进行参数相关的调用。”
发布于 2011-01-09 19:44:28
Windows头文件中的数万个宏绝对是令人讨厌的。到目前为止我能想到的最好的办法就是
包括<windows.h>
#include #undef ExpandEnvironmentStrings //起飞,WinAPI!命名空间源{ std::wstring ExpandEnvironmentStrings(const std::wstring& WindowsApi );}
但是#2是最后的手段,严格遵守#1可以实现更多的目标。
https://stackoverflow.com/questions/4638824
复制相似问题