有没有一种将C++编译为C代码的方法?

25

我有一个程序,用户使用C ++类进行配置,并且应该使用相同的类来配置只能使用C99子集(Open CL语言)的程序。

所以我的问题是: 是否有一种将C ++编译为C代码的方法?

开源的解决方案最好!


1
可能是C++转C的重复问题 - Kirill V. Lyadvinsky
18
这是一个可爱的说法,这是一个已被关闭为“不是真正问题”的问题的副本... - 6502
7
将一些C++代码嵌入到您的C代码中的常规方法不是将其转换为C。相反,您需要在C++代码周围放置一个包装器API,其中包括 extern "C" 函数,然后使用能够生成与您的C编译器使用的相同链接器兼容的对象文件的C++编译器进行编译,并将所有内容链接在一起。如果您的平台没有提供兼容的C和C++编译器(我认为最可能的原因是它根本没有提供C++编译器/运行时),则转换将是最后的选择。 - Steve Jessop
OpenCL 2.2现在支持C++内核。https://www.khronos.org/news/press/khronos-releases-opencl-2.2-provisional-spec-opencl-c-kernel-language - Lena
"可能是链接的重复", "可能是链接的重复", "可能是链接的重复"。他们是机器人吗? - Taureon
显示剩余4条评论
5个回答

23

C++ FAQ中列举了一些可能性:是否可以将C++转换为C?

简而言之,它表示您不能期望通过此方法得到特别易读的代码。考虑到涉及的复杂性有:多重继承,虚函数解析,模板,运算符重载等,这些概念在纯C语言中没有清晰简洁的表达方式。但是,如果你只需要可编译的C代码,那么这可能是一个可行的方法。


实际上,你列出的所有内容在可移植的纯C中都不是特别难实现 - 尽管可能会很冗长。然而,当你拥有MI时,在可移植的纯C中指向成员函数和数据成员的指针就更难了。 - Fred Nurk
2
@Fred:我并不认为这些实现起来很困难,但它们确实非常繁琐!但是没错,你说得对;主要的障碍是冗长。 - Oliver Charlesworth
1
例如,struct A:B,C{}; 变成 struct A {struct B __base_subobject_1; struct C __base_subobject_2;};。虚函数解析可以通过vtable进行,它只是一个函数指针数组(大多数人都熟悉这个)。模板可以按照C ++的要求精确实例化,使用像__vector__int这样的名称表示vector<int>。运算符重载可以简单地成为一个命名函数:__SomeType_add用于a + b; 由于您在C ++中解决了重载问题,因此您知道C调用的确切内容。 - Fred Nurk
1
啊,我可能误读了它,以为是“复杂性……在纯C中没有清晰的表达方式。” 但对于那些列出的概念,有干净的表达方式! - Fred Nurk
@Fred:我稍微修改了我的回答措辞! - Oliver Charlesworth

23

你可以使用clang C++ 前端生成 LLVM 字节码,并使用 llc 生成 C 代码,详见llc文档,特别是 c 选项。二者均为开源软件,使用类 BSD 许可证。


4
如果生成的代码除了构建之外不需要执行任何操作,那么这可能是最佳选择。不要期望 llc 的输出代码易读性很高。 - rubenvb
2
如果你想要小而高效,易读的C代码,我认为最好的方法就是用C语言编写。好吧,CUDA将允许您使用C++来完成您想要的工作,但如果OpenCL不能这样做,并且相同的配置代码需要在两者上工作...并不是世界上所有东西都需要成为类,不是吗?;-) - Steve Jessop
8
请注意,llc -c选项似乎已经被弃用。该手册不再提及它。 - eonil
3
考虑到其存在缺陷且无人愿意维护它(至少这是弃用的原因)。 - Mikhail Maltsev
1
一个保留了C后端的LLVM分支现在位于https://github.com/JuliaComputing/llvm-cbe。 - technosaurus
显示剩余2条评论

10

看起来Comeau编译器能够做到这一点。根据维基百科,“Comeau C/C++不像其他编译器那样直接生成可执行文件,而是输出C代码,并需要一个单独的C编译器才能生成最终程序。”

虽然我从未尝试过。


Comeau的工作方式如描述所示。它根据对每个后端编译器优化代码的了解,为特定的后端编译器量身定制C输出。 - Thomas Edleson

5
  1. VisualGBD是一款Visual Studio扩展,允许您开发和编译嵌入式平台。它不是免费的,但有试用版。如果适用于您的应用程序,我认为它是值得的。

    https://visualgdb.com

  2. LLVM曾经是一个不错的选择,但现在已经停止了更新。(C后端已经被重新启用here,并且可能会使以下说明起作用)

    http://llvm.org/docs/FAQ.html#translatecxx

    它可以处理一些代码,但对于更复杂的实现,它将失败,因为它还没有完全更新到一些现代C++约定。因此,请尝试频繁编译您的代码,直到您了解允许的内容。

    命令行的使用语法如下(版本9.0.1):

    clang -c CPPtoC.cpp -o CPPtoC.bc -emit-llvm
    clang -march=c CPPtoC.bc -o CPPtoC.c
    

    对于旧版本(不确定过渡版本),请使用以下语法:

    llvm-g++ -c CPPtoC.cp -o CPPtoC.bc -emit-llvm
    llc -march=c CPPtoC.bc -o CPPtoC.c
    

    请注意,它创建了GNU风格的C而不是真正的ANSI C。在您过度投入代码之前,请测试一下这是否对您有用。例如,某些嵌入式系统只接受ANSI C。

    还要注意,它生成的代码功能性强但相当难以阅读。我建议注释和维护您的C++代码,不要担心最终的C代码。

  3. 遗憾的是Comeau网站已经关闭。Coherent是基于Comeau构建的,可能会提供一些选项。他们有预构建的虚拟机,最近更新至2018年。

    https://www.autometer.de/unix4fun/coherent/#inst_coh

  4. Cfront可用,但已经很长时间没有更新了。

    http://www.softwarepreservation.org/projects/c_plus_plus/cfront/release_3.0.3/source/cfront_3_0_3.tgz


1
LLVM似乎已经移除了C后端,因此在最近的版本中无法直接使用,但是它似乎已经在这里被重新启用:https://github.com/JuliaHubOSS/llvm-cbe - Catskul

2
  1. Comeau Computing提供基于Edison Design Group前端的编译器,输出C代码。
  2. LLVM是可下载的编译器,可以发出C代码。此外还可以在这里和这里查看。以下是通过LLVM将C++转换为C的示例。
  3. C++的原始实现是由AT&T的Bjarne Stroustrup和其他人生成的Cfront,它生成C代码。但是它有两个问题:自90年代中期开始进行所有权更改迷宫后很难获得许可证,并且开发在同一时间停止,因此不会得到错误修复并且不支持任何新的语言特性(例如异常、名称空间、RTTI、成员模板)。
  4. 与流行的神话相反,在撰写本文时不存在将C++转换为C的g++版本。这样的事情似乎是可行的,但我不知道是否有人已经做到了(尚未)。

http://www.cs.technion.ac.il/users/yechiel/c++-faq/convert-to-c.html


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