【问题标题】:Is there a way to compile C++ to C Code? [closed]有没有办法将 C++ 编译为 C 代码? [关闭]
【发布时间】:2011-02-19 10:54:19
【问题描述】:

我有一个由用户使用 C++ 类和 应该使用相同的类来配置一个程序 只能使用 C99(开放 CL 语言)的子集。

所以我的问题是: 有没有办法将 C++ 编译为 C-Code?​​p>

开源会很棒!

【问题讨论】:

  • C++ to C conversion的可能重复
  • 很高兴地说这是一个问题的重复,该问题被关闭为不是一个真正的问题......
  • 另外请注意,将 sn-p 转换为单个类与以 C 源代码为目标编译整个 C++ 程序之间存在差异。下面的答案中提到的一些工具不会让您从 C 程序中真正调用您的配置类(用 C++ 编写并转换为可能不可读的 C),或者至少不会轻松做到这一点。如果该进程完全导出 C++ 函数,那么它们的名称将被破坏,这是第一个障碍。
  • 使某些 C++ 代码可从 C 代码调用的常用方法不是将其转换为 C。而是在 C++ 代码周围放置一个包装 API,包括extern "C" 函数,然后使用 C++ 编译器对其进行编译,该编译器生成与 C 编译器使用的相同链接器兼容的目标文件,并将所有内容链接在一起。如果您的平台不提供兼容的 C 和 C++ 编译器,转换将是最后的手段(我认为最可能的原因是它根本不提供 C++ 编译器/运行时)。
  • 如果遇到我的问题,我只是在处理没有继承的简单类,我正在使用 Open CL C 平台link,它被认为是用于显卡等等,我不明白一个 C++ 编译器。我的问题是 CUDA 部分支持 C++,我的程序应该完成一个软件,所以最好将源代码指定为 c++ 类,而不是做两次容易出错的工作。

标签: c++ c compiler-construction compiler-theory


【解决方案1】:

您可以使用clang C++ 前端生成llvm 字节码,并使用llc 发出C 代码,请参阅llc doc,尤其是c 选项。两者都是开源的,具有类似 BSD 的许可证。

【讨论】:

  • 如果生成的代码除了构建不需要做任何事情,这可能是最好的选择。不要指望llc 的输出是任何可读的代码。
  • @cl_progger:如果你想要小巧、高效、可读的 C 代码,那么我认为最好的办法是用 C 编写它。好的,所以 CUDA 允许你使用 C++ 来做你想做的事情,但是如果 OpenCL 没有,并且相同的配置代码需要在两者上工作......不是世界上的所有东西都需要成为一个类,不是吗? ;-)
  • 仅供参考。 llc -c 选项似乎已被弃用。 The manual 不再提及。
  • 它被认为是错误的,没有人愿意维护它(至少这是它被弃用的原因)
  • 保留了 C 后端的 llvm 分支现在位于 github.com/JuliaComputing/llvm-cbe
【解决方案2】:

C++ 常见问题解答有一个可能性列表:Is it possible to convert C++ to C?

简而言之,它表示您不能指望这会为您提供特别可读的代码。想想所涉及的复杂性;多重继承、虚函数解析、模板、运算符重载等。在纯 C 中没有 clean 简洁的方式来表达这些概念。但是,如果您所追求的只是可编译的 C,那么这可能是要走的路。

【讨论】:

  • 实际上,您列出的任何内容都很难在可移植的纯 C 中实现——尽管它可能很冗长。但是,当您拥有 MI 时,指向成员函数的指针和指向数据成员的指针会更难(在可移植的纯 C 语言中)。
  • @Fred:我并不是说这些实施起来困难,但实施起来却非常乏味!但是,是的,你是对的;主要障碍是冗长。
  • 例如 struct A : B, C {};变成 struct A { struct B __base_subobject_1;结构 C __base_subobject_2; };。虚函数解析可以通过一个 vtable 进行,它只是一个函数指针数组(大多数人对此都很熟悉)。模板可以通过完全按照 C++ 的要求实例化它们来工作,使用像 __vector__int 这样的名称来表示 vector。运算符重载可以简单地是一个命名函数:__SomeType_add for a + b;由于您在 C++ 中解决了重载,因此您确切地知道 C 调用了什么。
  • 啊,我一定把它误读为“复杂性......在纯 C 中表达这些概念没有干净的方式。”列出的方法有干净的方法!
  • @Fred:我稍微修改了答案中的措辞!
【解决方案3】:

Comeau 编译器似乎能够做到这一点。来自Wikipedia“Comeau C/C++ 不是直接生成可执行文件,而是输出 C 代码,并且需要单独的 C 编译器才能生成最终程序。”

不过,我从未尝试过。

【讨论】:

  • Comeau 按描述工作。它根据每个后端编译器如何优化代码的知识,为特定的后端编译器定制 C 输出。
【解决方案4】:
  1. VisualGBD 是一个 Visual Studio 扩展,允许您为嵌入式平台进行编译开发。它不是免费的,但有试用版。如果它适用于您的应用程序,我认为它值得。

    https://visualgdb.com

  2. LLVM 是一个不错的选择。

    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. CLang可用但很久没有更新

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

【讨论】:

    【解决方案5】:
    1. Comeau Computing 提供基于 Edison Design Group 前端的编译器,可输出 C 代码。
    2. LLVM 是一个可下载的编译器,它发出 C 代码。另请参阅此处和此处。这是通过 LLVM 将 C++ 转换为 C 的示例。
    3. Cfront 是 C++ 的原始实现,由 Bjarne Stroustrup 和 AT&T 的其他人完成,它生成 C 代码。但是它有两个问题:自 90 年代中期开始经历所有权变更的迷宫以来,很难获得许可证,同时开发停止,因此它没有得到错误修复,也不支持任何较新的语言功能(例如,异常、命名空间、RTTI、成员模板)。
    4. 与流行的神话相反,在撰写本文时,还没有将 C++ 转换为 C 的 g++ 版本。这样的事情似乎是可行的,但我不知道是否有人真正做到了(目前)。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      • 1970-01-01
      • 2012-05-20
      • 2023-03-06
      • 2011-02-24
      相关资源
      最近更新 更多