【问题标题】:Visual Studio 2015: Extern "C" and the "export" keywordVisual Studio 2015:外部“C”和“export”关键字
【发布时间】:2018-11-05 16:55:23
【问题描述】:

我正在将一个大型项目从 VS2012 迁移到 VS2015(我知道是小步骤),我遇到了一个问题,即 C 头文件不再编译,在保留的 c++ 关键字上出错 - 即使它们'重新包含在外部 C 中。

这是一个简化的示例(在 2012 年编译,但不是 2015 年)

main.cpp

extern "C" {
    #include "cheader.h"
}

int main()
{
    printfFromC();
    return 0;
}

cheader.h

#ifndef HEADER_H
#define HEADER_H

extern int export;
int printfFromC();

#endif

ctest.c

#include "cheader.h"
#include <stdio.h>

int export = 0;

int printfFromC()
{
    export++;
    return printf("Hello from C (invocation %d) !\n", export);
}

出现以下错误:

------ Build started: Project: ConsoleApplication1, Configuration: Debug Win32 ------
  main.cpp
c:\[...]\cheader.h(4): warning C4091: 'extern ': ignored on left of 'int' when no variable is declared
c:\[...]\cheader.h(4): error C2143: syntax error: missing ';' before 'export'
c:\[...]\cheader.h(4): error C3378: a declaration can be exported only from a module interface unit

编辑:

我在创建示例时犯了一个错误 - 导致问题的关键字是 export - 不是我最初想到的任何 c++ 保留关键字。下面的示例已修改为使用int export 而不是int new

【问题讨论】:

  • @NathanOliver 我在创建示例时犯了一个错误 - 导致问题的关键字是 export - 不是我最初想到的任何 c++ 保留关键字。
  • export也是C++中的保留字
  • @NeilButterworth 是的 - 但不同的是这个例子现在是在 2012 年编译的。
  • 因为你古老的编译器没有正确支持 C++11 标准。

标签: c++ c visual-studio


【解决方案1】:

extern "C" 的使用控制了它所应用的代码的名称修改——它不会神奇地使编译器将该代码编译为 C。所以当你 #include 时,@987654324 中包含 extern int export; 的标头@,它被编译为 C++ 代码,而 export 是 C++ 中的保留字,所以会出现语法错误。

【讨论】:

  • 这并不能解释为什么它在 VS2012 中编译 - 我正在迁移的应用程序引用了具有这些关键字的 C 库头文件。
  • 因为 VS2012 没有正确支持 C++11 标准所以可以编译。
【解决方案2】:

new 是 C++ 中的关键字。您不能将其用作交叉编译代码中的标识符。这就是错误的原因。您必须为变量想一个不同的名称。

请注意,将 C++ 翻译单元的一部分放入extern "C" { ... } 区域并不意味着代码将以某种方式编译为 C 代码。它只是意味着该地区的外部实体将获得 C 链接。代码本身仍被编译为 C++ 代码,所有 C++ 特定的限制仍然适用。

【讨论】:

    【解决方案3】:

    进一步挖掘,这里建议的 hack 似乎有效:https://stackoverflow.com/a/36869181/1486100

    按以下方式更改 main.cpp 即可编译。

    extern "C" {
        #include "cheader.h"
    }
    
    int main()
    {
        printfFromC();
        return 0;
    }
    

    extern "C" {
        #define export extern_export
        #include "cheader.h"
        #undef export
    }
    
    int main()
    {
        printfFromC();
        return 0;
    }
    

    【讨论】:

    • 是的,毫无疑问,将名称 export 更改为其他名称将解决问题。但前提是原始名称从未在任何地方使用,在这种情况下,为什么不将其完全删除?
    • 不,它不起作用,因为它只影响外部声明而不影响变量定义。现在您的 extern_export 变量未定义。
    • @AnT:不知道你的意思是什么——它改变了关键字定义的变量名的名称,但实际上并不影响 c++ 应用程序将使用的任何东西,因为它不能使用反正这些名字。这允许它编译。它动态链接的任何内容仍将按预期工作。
    • @NeilButterworth 这是一个简化的示例 - 我正在尝试解决我们无法更改的供应商库。
    • @Tyzoid 我的观点是,如果您尝试在 C++ 代码中以新名称使用此变量,您最终会出现链接器错误,因为该变量未定义。显然,您不想在 C++ 端使用此变量,而只想编译标头 - 这是您忘记提及的重要细节。
    猜你喜欢
    • 2017-07-07
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多