我有一个C++ 14文件my.cpp,在其中我尝试使用一个名为open62541的C99库。对于后者,完整的源open62541.c/.h和库libopen62541.a都存在。在my.cpp中,其中包括open62541.h,我使用的是C++特定代码(例如iostream),因此从技术上讲,我正在混合C和C++。

我可以通过引用my.cpp来使libopen62541.a成功编译:

gcc -x c++ -std=c++14 -Wall my.cpp -l:libopen62541.a -lstdc++ -o out

这不会输出任何警告,并创建可执行文件。

但是,如果我尝试仅使用源代码进行编译:
gcc -x c++ -std=c++14 -Wall my.cpp open62541.c -lstdc++ -o out

我收到许多ISO C++警告(例如,“ISO C++禁止将字符串常量转换为'char'*”)和源自open62541.c内部的一些“跳转至标签”错误,导致编译失败。

我可以使用-fpermissive开关使编译成功:
gcc -x c++ -std=c++14 -Wall my.cpp open62541.c -lstdc++ -fpermissive -o out

仍然会输出很多警告,但会成功创建可执行文件。但是,我不确定这样做是否是个好主意。

也许值得一提的是open62541.h在开始时就考虑了C++:
#ifdef __cplusplus
extern "C" {
#endif
  • 假定.a库与open62541库代码 bundle 在一起,应该是从同一来源构建的,为什么前两种方法在生成警告和错误方面不一致?为什么一个起作用而另一个不起作用?
  • 是否应该首选一种方法-链接.a与引用.c的方法?我的印象是它们应该等效,但显然不是。
  • 在这种情况下,是否使用-fpermissive可能会掩盖潜在的问题,因此应避免使用?
  • 最佳答案

    您看到的错误(和警告)是C++编译器在编译C代码时输出的编译错误(和警告)。

    例如,在C中"literal"的类型为char[],而在C++中,其类型的类型为const char[]

    您将获得一个C++编译器从libopen62541.a构建open62541.c,您将看到相同的错误(警告)。但是C编译器可能会满意(取决于该C源文件的状态)。

    另一方面,当您编译my.cpp并将其与libopen62541.a链接时,编译器不会看到有问题的C代码,因此不会出现错误(警告)。

    从这里开始,您基本上有两个选择:

  • 如果适合您,请使用预编译的库
    g++ -std=c++14 -Wall -Wextra -Werror my.cpp -lopen62541.a -o out
    
  • 如果需要修改库代码,请首先进行编译
    gcc -Wall -Wextra -Werror -c open62541.c
    g++ -std=c++14 -Wall -Wextra -Werror -c my.cpp
    g++ open62541.o my.o -o out
    
  • 09-25 15:22