C/C++,能否将文件包含到字符串字面值中?

53

我有一个C++源代码文件和一个Python源代码文件。我希望C++源文件能够使用Python源文件的内容作为一个大字符串文字。我可以像这样做:

char* python_code = "
#include "script.py"
"

但这样做行不通,因为每行末尾都需要加上 \ 。我可以手动复制并粘贴Python代码的内容,用引号和终止符 \n 围绕每一行,但那样很丑陋。即使Python源代码实际上将被编译成我的C ++应用程序,我仍希望将其放在单独的文件中,因为这样更有条理,并且与编辑器更好地配合(像Emacs无法智能识别C字符串文字是Python代码,并在其中切换到Python模式)。

请不要建议我使用PyRun_File,因为这正是我试图避免的 ;)


4
如果这是重复的,请您提供一个链接。我搜索了一下,但没有看到任何与我的搜索词相关的内容。 - Joseph Garvin
此外,之前的版本是特定于Python的吗?因为这是一个更一般性的问题。 - Joseph Garvin
1
顺便说一下,除非它非常琐碎,否则嵌入Python脚本是不好的形式。我们工作中的人会这样做,当我们更改Python环境中的内容但错过更新他们的代码时,这会导致各种问题,因为它在.cpp文件中! - Christopher
这是半微不足道的,它们是单元测试的一部分。 - Joseph Garvin
有趣的是,链接到的重复问题是关于C语言的,然而那里的最佳答案却仅适用于C++11。 :-/ - Emile Cormier
7个回答

43

C/C++预处理器按照标记单元操作,而字符串字面量是一个单一的标记单元。因此,您不能打断字符串字面量的中间部分。

您可以将script.py预处理成类似以下内容的形式:

"some code\n"
"some more code that will be appended\n"

可以使用xxd -i生成一个可随时包含的C静态数组,也可以包含那个头文件。


20
对于xxd,点赞(+1)。脚本可能不一定需要是字符串字面值。 - Steve Jessop
你怎么预处理 script.py 呢?我没有看到 CPP 有这样的功能。除非你也是指使用像 sed 这样的外部工具。 - Joseph Garvin
一个外部工具,是的。你不能仅使用CPP做你想做的事情。 - bdonlan
1
对于那些开启了-Wall -Wextra选项的人,如果使用此技巧来生成文件并将值分配给const char[],则可以通过xxd命令和xargs命令运行输出:xxd -i some-file.txt | xargs printf "(char)%s"。虽然不太美观,但它能发挥作用。 - Qix - MONICA WAS MISTREATED

16
这并不能完全解决问题,但它会让你接近成功。
假设script.py包含以下内容:
print "The current CPU time in seconds is: ", time.clock()

首先,像这样包装起来:
STRINGIFY(print "The current CPU time in seconds is: ", time.clock())

然后,在包含它之前,执行以下操作:
#define STRINGIFY(x) #x

const char * script_py =
#include "script.py"
;

可能还有更紧凑的答案,但我仍在寻找。


1
先生,您有一个饼干!困扰已经持续了2年。 - Bebe Carabina
1
我曾经遇到一个(很少见的)情况,有时需要将同一个文件作为代码包含,有时需要将其作为字符串包含(别问我为什么; )。 因此,我在被包含的文件中添加了 #ifndef STRINGIFY \n #define STRINGIFY(x) x \n #endif,当我想将其作为代码包含时,我确保未定义STRINGIFY。神奇的是,它也适用于多行文件! - Marcin Zukowski
我认为这个答案比被采纳的答案更有帮助,但它还不够完美。它仍然需要对被包含的文件进行一些修改。我想知道是否有人找到了任何解决方法? - Shabgard

4
最好的方法是将文件作为资源包含到环境/工具集中(如果有此功能)。如果没有(如嵌入式系统等),您可以使用bin2c实用程序(类似于http://stud3.tuwien.ac.at/~e0025274/bin2c/bin2c.c)。它将获取文件的二进制表示并生成一个C源文件,其中包含一个初始化为该数据的字节数组。如果您希望该数组以'\0'结尾,则可能需要对工具或输出文件进行一些调整。 将运行bin2c实用程序合并到您的makefile中(或作为驱动构建的任何内容的预构建步骤)。 然后只需将文件编译并链接到应用程序中,您就可以在一个内存块中看到您的字符串(或文件的其他映像),该内存块由该数组表示。
如果您将一个文本文件包含为字符串,需要注意的一件事情是行尾可能与函数所期望的不匹配 - 这可能是您想要添加到bin2c实用程序中的另一件事情,或者您需要确保您的代码正确处理文件中存在的任何行尾。也许可以修改bin2c实用程序,添加一个“-s”开关,表示您希望将文本文件作为字符串合并,这样行尾就会被规范化,并且数组末尾会有一个零字节。

文件链接已失效。你有备份吗? - kenorb

1

你需要对Python代码进行一些处理,以处理其中出现的任何双引号、反斜杠、三字符序列和可能出现的其他内容。同时,你可以将换行符转换为\n(或反斜杠转义它们),并在两端添加双引号。结果将是从Python源文件生成的头文件,然后你可以使用#include命令将其包含进来。使用构建过程自动化此过程,这样你仍然可以像编写Python一样编辑Python源代码。


1

你可以在构建过程中使用Cog(进行预处理和嵌入代码)。我承认这样做的结果可能不是理想的,因为你最终会在两个地方看到代码。但每当我看到“Python”、“C++”和“预处理器”这些词紧密相连时,我觉得它值得一提。


-1

这里是如何使用cmd.exe自动转换的方法

------ html2h.bat ------

@echo off
echo const char * html_page = "\
sed "/.*/ s/$/ \\n\\/" ../src/page.html | sed s/\"/\\\x22/g 
echo.
echo ";

它被称为

cmd /c "..\Debug\html2h.bat" > "..\debug\src\html.h"

并附加到代码中

#include "../Debug/src/html.h"
printf("%s\n", html_page);

这是一个相当依赖于系统的方法,但像大多数人一样,我不喜欢十六进制转储。


-11
使用 fopengetlinefclose

3
这相当于PyRun_File。这个想法是在编译时将它捆绑到可执行文件中,这样我就不必再做那种事情了。 - Joseph Garvin
2
这将获取正在执行的机器上文件的运行时内容,而不是构建机器上文件的编译时内容。 - not-a-user

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接