首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Windows头文件中是否有禁用定义TCHAR中立函数名宏的设置?

Windows头文件中是否有禁用定义TCHAR中立函数名宏的设置?
EN

Stack Overflow用户
提问于 2011-01-09 19:10:03
回答 2查看 802关注 0票数 0

假设我在ExpandEnvironmentStringsW周围实现了一个简单的包装器

//ExpandNStuff.hpp:

代码语言:javascript
复制
#include <string>
namespace WindowsApi
{
    std::wstring ExpandEnvironmentStrings(const std::wstring& source);
}

//ExpandNStuff.cpp:

代码语言:javascript
复制
#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时会发生什么

代码语言:javascript
复制
#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

代码语言:javascript
复制
#ifdef ExpandEnvironmentStrings
#undef ExpandEnvironmentStrings
#endif

但是,对每个API执行此操作可能会很繁琐。我宁愿被强迫显式地调用函数的"W“或"A”版本,也不愿被像这样的#define bug咬到。有没有办法关闭宏?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-01-09 19:23:09

它们的定义没有包装在任何宏中。

代码语言:javascript
复制
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)进行参数相关的调用。”

票数 3
EN

Stack Overflow用户

发布于 2011-01-09 19:44:28

Windows头文件中的数万个宏绝对是令人讨厌的。到目前为止我能想到的最好的办法就是

包括<windows.h>

  • punctually在内的
  1. 严格限制不定义出现的任何内容:

#include #undef ExpandEnvironmentStrings //起飞,WinAPI!命名空间源{ std::wstring ExpandEnvironmentStrings(const std::wstring& WindowsApi );}

但是#2是最后的手段,严格遵守#1可以实现更多的目标。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4638824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档