如何将 Visual Studio 宏值放入预处理器指令中?

2024-04-09

在我的项目中,我需要访问的价值$(SolutionDir)运行时的宏。为此,我尝试添加预处理器条目,例如DEBUG_ROOT=$(SolutionDir) or DEBUG_ROOT=\"$(SolutionDir)\"但这会由于无效的转义序列而导致各种编译器错误,因为$(SolutionDir)包含单个\字符(例如$(SolutionDir) = c:\users\lukas\desktop\sandbox\).

有没有一种简单的方法来传递值$(SolutionDir)宏到我的代码中?

背景

我正在利用函数OutputDebugString(..)我的调试版本中有很多内容是为了查看我的代码正在做什么。

/* debug.h */
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define LOCATION __FILE__ "(" TOSTRING(__LINE__) ") : "

#if !defined(DEBUG_ROOT)
#define DEBUG_ROOT    "#"   /* escape string to force strstr(..) to fail */
#endif

/*
**  DBGMSG macro setting up and writing a debug string.
**  Note: copying the strings together is faster than calling OutputDebugString(..) several times!
**  Todo: Ensure that size of dbgStr is not exceeded!!!
*/
#define DBGMSG(text) \
    { \
        char dbgStr[1024]; \
        char *pFile; \
        pFile = strstr(LOCATION, DEBUG_ROOT); \
        if (pFile == LOCATION) \
        { \
            wsprintf(dbgStr, ".%s", pFile + strlen(DEBUG_ROOT)); \
        } \
        else \
        { \
            wsprintf(dbgStr, "%s", LOCATION); \
        } \
        wsprintf(dbgStr, "%s%s", dbgStr, text); \
        OutputDebugString(dbgStr); \
    }


/* somewhere in the code */
DBGMSG("test")

使用截图会导致打印输出像c:\users\lukas\desktop\sandbox\testconsole\main.c(17) : test在 Visual Studio 的输出窗口中。这可以加快在代码中查找导致打印输出的位置,因为您只需双击输出窗口的行,Visual Studio 就会自动跳转到指定的代码位置。

因为根据解决方案的位置,绝对路径 (__FILE__扩展为绝对路径)调试字符串的“标头”可能会变得相当长。我发现 Visual Studio 足够聪明,可以理解相对路径,例如解决方案根目录。为了减少字符串的长度,我正在检查是否__FILE__是在一个DEBUG_ROOT目录,如果是的话我要替换DEBUG_ROOT用一个简单的'.'生成相对路径DEBUG_ROOT。所以如果我写#define DEBUG_ROOT "c:\\users\\lukas\\desktop\\sandbox"上面示例的最终调试字符串将是.\testconsole\main.c(17) : test。目前我正在设置的值DEBUG_ROOT在项目的预处理器定义内。

由于有几个人正在处理该项目,因此在项目设置中拥有绝对路径并不是明智之举,因为每个团队成员都可能将源文件签出到不同的根目录。所以我尝试使用$(SolutionDir)宏来创建类似的东西DEBUG_ROOT=\"$(SolutionDir)\\"。但这样做我就会遇到麻烦。自从$(SolutionDir) = c:\users\lukas\desktop\sandbox\扩大的DEBUG_ROOT导致未定义的转义序列、未终止的字符串和更多丑陋的编译器错误......

Solution

根据以下的回答kfsone https://stackoverflow.com/users/257645/kfsone我提出了以下解决方案,可以传递 Visual Studio 宏的任何值,例如$(SolutionDir)到你的代码中。以下解决方案与所使用的 Visual Studio 版本和语言 C/C++ 无关。

Adding SOLUTION_DIR=\"$(SolutionDir)"项目的预处理器条目会产生一个编译器命令行,如下所示:

/Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "SOLUTION_DIR=\"C:\Users\Lukas\Desktop\sandbox\""
/Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /nologo /c /Wp64 /ZI /TP
/errorReport:prompt

注意$(SolutionDir)前面有一个\"创建一个"值前面的字符$(SolutionDir)但由单个终止"。查看编译器的命令行显示终止"被最后一个逃脱\ of $(SolutionDir).

Using SOLUTION_DIR在您的代码中会导致未知的转义序列,并且字符串以所有结尾\字符被删除。这是由编译器完成的,它扩展了SOLUTION_DIR并解释\作为转义序列的开始。

使用TOSTRING(x)上面发布的代码宏解决了这个问题,因为它强制编译器按原样使用字符串而不进行进一步处理。

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

#define SOLUTION_DIR2   TOSTRING(SOLUTION_DIR)

// the following line may cause compiler warnings (unrecognized character escape sequence)
printf("%s\n", SOLUTION_DIR);    // prints C:UsersLukasDesktopsandbox 

// the following line compiles without any warnings
printf("%s\n", SOLUTION_DIR2);   // prints "C:\Users\Lukas\Desktop\sandbox"

从这里开始,只需执行一些字符串魔术即可删除"字符来自SOLUTION_DIR2.


Visual Studio 2013 及更高版本中提供了一项 C++11 功能(原始字符串文字),可让您执行此操作。语法是

'R"' <delimiter> '(' <string> ')' <delimiter> '"'

例如如果你选择“?:?”作为你的分隔符

R"?:?(don't\escape)?:?"

或者如果您选择“Foo123”

R"Foo123(don't\escape)Foo123"

但对于这个演示,我要选择?作为单字符分隔符,因为我们知道它在 Windows 文件名中是非法的。

现在您可以设置项目级预处理器定义:

DIR=R"?(C:\\Temp\\)?"

然后以下代码生成预期的输出

#include <iostream>
int main() {
    std::cout << DIR << '\n';
}

writes

C:\\Temp\\

代替

C:\Temp\

现在捕获 SolutionDir 宏就很简单

DIR=R"?($(SolutionDir))?"

如果这很麻烦,您可以在属性表中添加自定义宏。转到“属性资源管理器”并右键单击您的项目,添加一个新的属性表,将其命名为“ProjectMacros.props”或其他名称。

展开您的项目并选择其中一种配置,例如调试,双击“PropertySheet”值打开“PropertySheet PropertyPages”并选择“UserMacros”

点击“添加宏”

Name: RawSolutionDir
Value: R"?path?($(SolutionDir))?path?"

您现在应该能够使用预处理器条目

SOLUTIONDIR=$(RawSolutionDir)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 Visual Studio 宏值放入预处理器指令中? 的相关文章

  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • 所有其他 Visual Studio“运行测试”尝试都会导致“无法启动程序 QTAgent32.exe”

    每当我运行测试 然后尝试再次运行测试时 都会收到以下错误 无法对测试运行进行排队 无法启动程序 C Program Files x86 Microsoft Visual Studio 10 0 Common7 IDE QTAgent32 e
  • 不幸的是应用程序已停止工作

    我是 Android 应用程序开发新手 我正在做这个教程应用程序 这是一个非常简单的应用程序 它从计数器中加一并减一 当我在模拟器中运行它时 它说 不幸的是教程已停止工作 代码中没有错误 API 级别是 17 请帮助我 java代码 pub
  • jquery isotope 具有无限滚动和图像预加载器

    我正在使用 jquery 同位素和无限滚动 并且想要使用图像预加载器 我使用的图像预加载器是这样的 图像预加载器 http code google com p img preloader image preloader loader ima
  • 在 Swift 上设置计时器

    我尝试重复执行函数 pepe 我没有收到错误 但它不起作用 这是我的代码 public class MyClass var timer Timer objc func pepe gt String let hola hola return
  • 对 Firebase Auth 帐户的密码实施自定义规则

    当用户创建帐户时 有什么方法可以设置密码的自定义规则吗 Firebase 似乎没有提供编辑密码规则的方法 我知道我可以在前端设置密码规则 但就像弗兰克 范普费伦 https stackoverflow com a 36319652 6516
  • Firefox 在重新加载时保留表单数据

    I have a big problem with the functionality in Firefox that keeps data that the user have filled in on reload F5 If i us
  • 从ini文件中读取数据

    我有一个需要输入文件名的 vbscript 代码是 Dim tsout Set tsout gofs CreateTextFile C csv Dim tsin Set tsin gofs OpenTextFile C csv 我该如何配置
  • Pandas 找到行的子集,在其他列约束下最小化列的总和

    我有一个非常简单的想法 即找到行的子集 使一列的总和最小化 而另一列的总和必须大于某个值 Example df pd DataFrame Names a b c d e f Target 35 15 12 8 7 5 Cost 15 40
  • DB 中的 Twitter 名称长度

    我正在向成员表添加一个字段 用于存储网站上成员的 Twitter 名称 据我所知 twitter 名称的最大长度为 20 因此显然我应该将字段大小设置为 varchar 20 SQL Server 这是一个好主意吗 如果 Twitter 开
  • 无法使用 Terraform 创建 google 项目

    我正在关注Google GKE 和 SQL 与 terraform https medium com mudrii google gke and sql with terraform 294fb84061教程 但我无法创建一个google
  • 如何将 AutoFixture 自定义应用到从基类继承的任何内容?

    为了干燥我的单元测试 我尝试使用 AutoFixture 作为 IoC 容器来实例化我的被测系统 SUT 在本例中是 ASP NET MVCControllers 因此 我想自定义 AutoFixture 以创建没有自动属性的控制器 我尝试
  • 获取 pandas 列中的第一和第二最高值

    我正在使用 pandas 来分析一些选举结果 我有一个 DF 结果 其中每个选区都有一行 代表各个政党 超过 100 个 的选票的列 In 60 Results columns Out 60 Index Constituency Regio
  • 如何在 Ubuntu 中为 Android 设置 Appium

    我是新来的appium 自动化测试技术 我使用的是运行 Ubuntu Linux 的 PC 我已经搜索过这个主题 但没有得到任何有用的教程 谁能指出我正确的文档 不要通过apt get安装nodejs 这需要sudo权限 如果以sudo用户
  • 如何使用 Mock.Of() 模拟没有默认构造函数的类?

    使用起订量 我需要在现有的基础上创建一个假的class 不是接口 有没有默认的ctor 我可以使用 传统 语法来做到这一点 var fakeResponsePacket new Mock
  • 当绑定属性更改时,ListView 分组不会更新

    我正在使用依赖项属性 GroupDescription 根据列表视图项目源的属性对 WPF 列表视图中的项目进行分组 我的问题是 仅当 GroupDescription 值更改时才会更新分组 而不是在列表视图源中项目的绑定属性更改后分组才会
  • iOS 6 中视图控制器的旋转不正确

    在我的应用程序中 我一直在使用现已弃用的 shouldAutoRotateToFace 方法 现在 当使用 iOS 6 模拟器时 当设备处于横向时 我的所有子视图都会旋转到纵向 有谁知道这可能是什么原因造成的 我已经尝试使用supporte
  • 将 Firebase Analytics 添加到 Instant App

    我正在将现有应用程序转换为 Android Instant App 我已经成功地做到了这一点 我的应用程序以即时应用程序形式运行 我现在面临的问题是关于 Firebase Analytics 当我运行即时应用程序时 出现此错误 E Fire
  • :: 运算符必须与 tolower() 一起使用吗?

    transform mystr begin mystr end mystr begin tolower 我正在使用转换函数使字符串全部小写字母 但即使在编写 using namespace std 之后在我的程序顶部 我收到一大堆错误 当像
  • 如何使用 Python 从网页的检查元素中获取数据

    我想使用 Python 从检查元素获取数据 我可以使用 BeautifulSoup 下载源代码 但现在我需要来自网页的检查元素的文本 如果您能建议我如何去做 我将不胜感激 编辑 我所说的检查元素是指 在谷歌浏览器中 右键单击为我们提供了一个
  • 如何将 Visual Studio 宏值放入预处理器指令中?

    在我的项目中 我需要访问的价值 SolutionDir 运行时的宏 为此 我尝试添加预处理器条目 例如DEBUG ROOT SolutionDir or DEBUG ROOT SolutionDir 但这会由于无效的转义序列而导致各种编译器