【问题标题】:How to compile C code that #includes C++ code?如何编译#includes C++代码的C代码?
【发布时间】:2015-06-29 19:21:13
【问题描述】:

我必须编译生成的带有#includes C++ 标头的C 代码,它才能在Linux、OS X 和Windows 上运行。我自己设置了#includes,以便能够与其中的 C++ 代码进行交互。

然而,C 代码使得严格的编译器会捕获可能被视为警告的错误。我想将这些作为警告传递出去,因为其中大部分是我无法控制的生成代码。

这是我编译它的尝试(我使用CMake,顺便说一句):

(我使用这些标志:-Wno-write-strings -Wno-error -fpermissive

  • 将整个项目视为 C++ 代码:在 Linux 上工作(使用 g++)但在 OS X 上我得到:

Clang:

error: assigning to 'char *' from incompatible type 'const char *'

g++:

/var/folders/hf/5dbkbqrx5p3bmnpdqqy4wgpr0000gn/T//ccvMHo2S.s:18:no such instruction: `vmovdqa LC0(%rip), %xmm3'
/var/folders/hf/5dbkbqrx5p3bmnpdqqy4wgpr0000gn/T//ccvMHo2S.s:19:no such instruction: `vmovdqa LC1(%rip), %xmm2'
/var/folders/hf/5dbkbqrx5p3bmnpdqqy4wgpr0000gn/T//ccvMHo2S.s:20:no such instruction: `vmovdqu (%rsi), %xmm7'
/var/folders/hf/5dbkbqrx5p3bmnpdqqy4wgpr0000gn/T//ccvMHo2S.s:21:no such instruction: `vmovdqu 16(%rsi), %xmm8'
/var/folders/hf/5dbkbqrx5p3bmnpdqqy4wgpr0000gn/T//ccvMHo2S.s:22:no such instruction: `vmovdqa LC2(%rip), %xmm1'
/var/folders/hf/5dbkbqrx5p3bmnpdqqy4wgpr0000gn/T//ccvMHo2S.s:23:no such instruction: `vpshufb %xmm3, %xmm7,%xmm6'
  • 将 C 代码视为 C 代码:

没有找到<atomic>

 fatal error: atomic: No such file or directory
 #include <atomic>

标志失效。

clang: error: unknown argument: '-q'
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated

标志仍然无效。

clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
clang: error: unsupported argument '-q' to option 'Wa,'

我该如何构建这个?

【问题讨论】:

  • 您最好的解决方案是像编译 C++ 一样编译所有文件。一个问题是名称修改。
  • 硬着头皮走:仅使用 C++ 将 C++ 包装在库中并公开 C 函数。
  • 您必须确保生成的 C 代码能够被 C++ 编译器接受,因为如果包含 C++ 头文件,则必须使用 C++ 进行编译。 clang 的错误告诉您(可能)将字符串文字分配给 char * 而不是 C++ 不允许的 const char *。不匹配的汇编器令人费解;这可能意味着您的 GCC 安装已损坏。
  • 您能否详细说明 GENERATED C 代码如何包含 C++ 标头? C 代码生成器肯定不会生成那些 C++ 包含的内容吗?我问这个的原因是,您似乎至少手动修改了生成的代码以包含这些标头。那么为什么不对其进行更多修改,使其作为 C++ 的一个子集被 C++ 编译器所接受呢?
  • @Sachin:多少是多少?这个过程可以通过一系列正则表达式替换以某种方式自动化吗?正如 Jonathan 已经评论的那样,没有 C 编译器能够读取任意 C++ 头文件。一个班级声明,你就完成了。链接将构成另一个障碍。如果您不想转换为 C++,您的标头至少应该是有效的 C。剩下的就是链接问题。

标签: c++ c compilation compiler-errors compiler-warnings


【解决方案1】:

对我来说,你似乎是在倒退解决这个问题。每个符合 C++ 的实现似乎都有一个兼容的 C ABI,因此 C++ 项目可以使用 C 库。充分利用它。

  1. 创建包含 C 代码的 C 库,并将它们编译为 C 代码(例如,cc -c your_filename.c 将生成一个 your_filename.o 目标文件)。
  2. 创建一个 C++ 项目(如果您仔细设计它们,您应该能够在其中包含所有 C 头文件),并在编译时使用链接器链接到您在步骤 1 中生成的 your_filename.o 目标文件项目。

【讨论】:

  • 第 1 步是不可能的。请参阅我在问题中的第二次尝试。
  • @SachinHosmani 您的 2. 尝试表明您在使用 #include &lt;atomic&gt; 时遇到错误,但这不是 C。C 通过 #include &lt;stdatomic.h&gt; 提供原子支持,您可能需要启用 C11 才能使可用。
  • @SachinHosmani 所以在你的 C++ 代码中使用 &lt;atomic&gt; 来锁定对你的 C 代码的访问,或者在你的 C 代码中使用 &lt;stdatomic.h&gt;(如@nos 所说)。
【解决方案2】:

我把#includes 放在自己能够与它的C++ 代码交互。

这就是你出错的地方。 #include.c 文件中使用 C++ 标头将永远不会起作用。

相反,您需要制作与 C 和 C++ 兼容的头文件。这些文件应该只包含 C 和 C++ 的公共子集中的代码;它们还应包含:

#ifdef __cplusplus
extern "C" { 
#endif

// main header code here

#ifdef __cpluscplus
}
#endif

以便包含此标头的 C++ 单元使用 C ABI 创建调用。

在此标头中,您可以声明一些函数,这些函数将与您的 C 文件所需的 C++ 代码进行交互。您可以在自己编写的新 C++ 源文件中实现这些功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-03
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-20
    • 2011-06-14
    相关资源
    最近更新 更多