预处理器愚蠢的做法(对 #include 进行字符串化)

2024-01-16

注意:这个问题与 OpenCL 本身无关......请检查最后一段以获取我的问题的简洁陈述。但提供一些背景:

我正在编写一些使用 OpenCL 的 C++ 代码。我喜欢将 OpenCL 内核的源代码保存在自己的文件中,以便于编码和维护(而不是直接将源代码作为字符串常量嵌入到关联的 C++ 代码中)。这不可避免地会导致一个问题,即在分发二进制文件时如何将它们加载到 OpenCL 运行时中——理想情况下,OpenCL 源代码包含在二进制文件中,这样二进制文件就不需要位于特定位置在某些目录结构中了解 OpenCL 源代码的位置。

我想将 OpenCL 文件作为字符串常量包含在某处,并且最好不使用额外的构建步骤或外部工具(为了跨编译器/跨平台的易用性......即,不xxd等)。我以为我偶然发现了一种基于第二个答案的技术this https://stackoverflow.com/questions/1415538/using-include-to-load-opencl-code线程,像这样:

#define STRINGIFY(src) #src

inline const char* Kernels() {
  static const char* kernels = STRINGIFY(
    #include "kernels/util.cl"
    #include "kernels/basic.cl"
  );
  return kernels;
}

请注意,我不想嵌入STRINGIFY如果可能的话,在我的 OpenCL 代码中添加宏(如上面引用的 SO 问题中所做的那样)。现在,这在 Clang/LLVM 编译器上运行得很好,但 GCC 却死得很惨(“未终止的参数列表调用宏 STRINGIFY”以及与 .cl 文件内容相关的各种语法“错误”出现)。所以,显然这种精确的技术不能跨编译器使用(没有尝试过 MSVC,但我希望它也能在那里工作)...我怎样才能最小化它以使其跨编译器工作?

总之,我想要一种符合标准的技术,将文件的内容作为 C/C++ 字符串常量包含在内,而无需调用外部工具或用无关代码污染文件。有想法吗?

EDIT:正如 Potatoswatter 指出的那样,上述行为是未定义的,因此不涉及接触要字符串化的文件的真正的交叉编译器预处理器技术可能是不可能的(第一个找出令人发指的黑客的人那does大多数/所有编译器的工作都会得到答案点)。出于好奇,我最终按照第二个回复中的建议进行了操作here https://stackoverflow.com/questions/1415538/using-include-to-load-opencl-code...也就是说,我添加了STRINGIFY直接宏到我包含的 OpenCL 文件:

In somefile.cl:

STRINGIFY(
  ... // Lots of OpenCL code
)

In somefile.cpp:

#define STRINGIFY(src) #src

inline const char* Kernels() {
  static const char* kernels =
    #include "somefile.cl"
    ;
  return kernels;
}

这在我尝试过的编译器中有效(Clang 和 GCC 也是如此,因为它在宏内部没有预处理器指令),并且至少在我的上下文中不是太大的负担(即,它没有)不干扰语法突出显示/编辑 OpenCL 文件)。像这样的预处理器方法的一个特点是,由于相邻的字符串被连接起来,因此您可以编写

inline const char* Kernels() {
  static const char* kernels =
    #include "utility_functions.cl"
    #include "somefile.cl"
    ;
  return kernels;
}

并且只要 STRINGIFY 宏都在.cl文件中,字符串被连接起来,允许您模块化您的 OpenCL 代码。


该标准最相关的部分是 §16.3/10:

由最外面的匹配括号界定的预处理标记序列形成了类函数宏的参数列表。列表中的各个参数由逗号预处理标记分​​隔,但匹配内括号之间的逗号预处理标记不会分隔参数。如果(在参数替换之前)任何参数不包含预处理标记,则行为未定义。如果参数列表中存在预处理标记序列,否则这些预处理标记将充当预处理指令,则行为未定义。

提取关键点:

  • 您需要将头文件括在一对括号内,以便宏不会认为文件中的每个逗号字符都会引入另一个参数。这些括号也将被字符串化,但应该不难解决。
  • Putting #include在参数列表中根本就是正式未定义的行为,因此这将是不可移植的。编译器正式不知道您是否希望结果字符串成为"#include \"kernels/util.cl\"".
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

预处理器愚蠢的做法(对 #include 进行字符串化) 的相关文章

随机推荐

  • 如何为 reStructuredText、Sphinx、ReadTheDocs 等设置自定义样式?

    我想扩展使用的主题Sphinx and 阅读文档与我自己的自定义样式 为了让我的更改得以保留 最好的方法是什么 编辑 截至 2021 年 以下答案已过时 请使用html css files 在你的conf py而不是使用版本 1 8 之后的
  • 如何为 wxWidgets OpenGL 程序启用多重采样?

    多重采样 http en wikipedia org wiki Multisample anti aliasing是一种申请方式全屏抗锯齿 FSAA 在 3D 应用中 我需要在我的 OpenGL 程序中使用多重采样 该程序当前嵌入在wxWi
  • 如何在 Jest 中模拟嵌套函数?

    我收到这个错误 Cannot find module httpsGet from functions getSecureString test js httpsGet 是我自己的功能 位于按钮处getSecureString js 并通过调
  • 使用 OuterRef 的简单子查询

    我正在尝试做一个非常简单的Subquery使用OuterRef 不是为了实际目的 只是为了让它工作 但我一直遇到同样的错误 posts models py code from django db import models class Ta
  • ASP.NET MVC 部分视图不调用我的操作

    我刚刚开始在 ASP NET MVC 上构建一个小型简单网站 在一个页面中我使用部分视图 部分视图代表一个简单的表单 应该在单击按钮时提交 如果我第一次单击它提交的时间成功并返回我的部分视图和验证消息 如果内容无效 但如果我想再试一次 则不
  • “由于共享主机中的‘LOG_BACKUP’,数据库的事务日志已满”

    我有一个 Asp Net MVC 5 网站 在共享托管计划中采用实体框架代码优先方法 它使用开源网站面板 http www websitepanel net 控制面板及其 SQL Server 面板有些限制 今天想编辑数据库的时候 遇到了这
  • Android 在 HttpClient 中收到 403 后得到响应

    我有这样的代码 HttpClient httpClient new DefaultHttpClient HttpPost httpPost new HttpPost server try JSONObject params new JSON
  • 当单个模型被多个视图共享时

    有两种观点 listView QtGui QListView tableView QtGui QTableView 我继续定义一个自定义DataModel供双方使用listView and tableView class DataModel
  • oops 的完整形式是什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 的完整形式是什么OOPS 有人说面向对象的编程结构其他人说面向对象的编程系统 哪一个是正确的 编程范式是OOP 面向对象编程 其他一切都可以从它
  • 材质 UI - 轮廓选择标签未正确渲染

    根据演示 Material UI 概述选择输入的标签应位于选择框的顶部边框的顶部 然而 在我的应用程序中 z index标签的似乎将其放置在顶部边框后面 因此看起来像一条线穿过标签 我几乎完全从文档中获取了代码 据我所知 没有任何样式与此输
  • AngularDart:使用反应式表单生成器创建表单

    我正在尝试使用创建AngularDart 5 angular forms 2 该API似乎与angular forms 1我不知道如何创建一个FormGroup using FormBuilder and ControlGroup 下面是我
  • python 中真的存在联合类型吗?

    由于Python是动态类型的 我们当然可以这样做 def f x return 2 if x else s 但这是 python 真正的用途吗 或者换句话说 联合类型是否像 Racket 中那样存在 或者我们只像这样使用它们 def f x
  • 使用git中的hooks导入和导出到csv

    我想知道这是否可能 创建连接到 cvs 的共享 git 存储库 post two hooks to it 每次有人从中提取时 它都会从 cvs 存储库导入 每次有人推送它时 它都会导出到 cvs 存储库 基本上创建一个对 git 用户完全透
  • XDT Transforms - 变换变换

    我正在创建一个 nuget 包 其中安装该包的部分结果是修改我的 web release config 我使用 web release config install xdt 将元素插入到此文件中没有问题 但我需要在要插入的元素上保留 xdt
  • Idris 中类型的模式匹配

    可能这是基本的 但我不明白为什么下面的函数回答 1fnc Nat并且 对于fnc 整数 它甚至没有作为模式包含在内 fnc Type gt Integer fnc Bool 1 fnc Nat 2 您不能对类型进行模式匹配 也不应该这样做
  • Leaflet - 可拖动标记和坐标以字段形式显示

    我必须做一个可拖动的标记 它的坐标应该显示在字段中 它将成为 PHP 联系表单的一部分 我创建了一个可拖动标记 请帮助我现在做什么 var marker L marker new L LatLng 53 471 18 744 draggab
  • GMap.net 中的缩放和平移

    我正在努力使GMap Net http greatmaps codeplex com 使用 WPF 内置事件控制启用多点触控 但我没有成功 我发现了一系列关于多点触控的文章 例如this http blogs msdn com b jaim
  • MVC4:嵌套部分视图丢失模型数据

    在 MVC4 项目中 我使用部分视图 该视图使用 ViewModel 并具有 GET 表单 在控制器操作中 我期望 ViewModel 对象包含一些数据 当将此部分放置在普通 cshtml 视图上时 我通过控制器操作中的预期 ViewMod
  • 开源拼写检查

    正在评估向我拥有的产品添加拼写检查 根据我的研究 需要做出的主要决定 要使用的库 词典 可以是特定地区的 英式英语 美式等 排除列表 每当检测到拼写错误时 它都可能不是拼写错误 而是 特定于用户的用语 此时用户应该能够将其添加到他的自定义排
  • 预处理器愚蠢的做法(对 #include 进行字符串化)

    注意 这个问题与 OpenCL 本身无关 请检查最后一段以获取我的问题的简洁陈述 但提供一些背景 我正在编写一些使用 OpenCL 的 C 代码 我喜欢将 OpenCL 内核的源代码保存在自己的文件中 以便于编码和维护 而不是直接将源代码作