【问题标题】:C++: Declaration of variable in global scope conflicts with declaration with C language linkageC++:全局范围内的变量声明与 C 语言链接的声明冲突
【发布时间】:2017-07-23 14:36:22
【问题描述】:

我有一些 InDesign 插件的旧代码,我正在尝试为使用支持 C++11 的编译器和 XCode 的新版本 InDesign 进行编译。

有一个头文件AdWrksSession.h,其中包含一个具有如下C 链接的类对象。 extern 对象/变量的声明如下:

extern "C" CAdWrksSession gAdWrksSession;

cpp 文件AdWrksSession.cpp 包含一个全局类对象,其默认构造函数与extern 对象同名:

CAdWrksSession gAdWrksSession;

旧的编译器没有为此显示任何错误消息,但是当它与 Apple 为支持 C++11 的 XCode 7.2.1 提供的新编译器一起使用时,它向我显示以下错误:

Declaration of 'gAdWrksSession' in global scope conflicts with declaration with C language linkage

我已尝试以下已针对C 链接提出的问题:

Compiler error for conflicting variable declarations: "conflicts with new declaration with 'C' linkage"

What is "extern linkage and with C language linkage"

Mixing declarations with extern, static and no storage specifier in global scope

我在header 文件中尝试了以下外部变量声明语法:

#ifdef __cplusplus
   extern "C" {
#endif
        CAdWrksSession gAdWrksSession;
#ifdef __cplusplus
    }
#endif

#ifdef COMPILE_FOR_C_LINKAGE
     extern "C" CAdWrksSession gAdWrksSession; 
#else
     extern "C++" CAdWrksSession gAdWrksSession;
#endif

但到目前为止没有任何效果。

当我将header 文件声明为static

static CAdWrksSession gAdWrksSession; //Header File

然后代码构建成功,但该功能当然不起作用。

更新: 如果我删除 C 链接,则会收到如下链接器错误:

Undefined symbols for architecture x86_64:
  "smart::gAdWrksSession", referenced from:
....//Names of generated object files
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 
(use -v to see invocation)`

有人可以帮我吗?谢谢。

【问题讨论】:

  • 如何在c中使用c++类?只是好奇。
  • 我不认为您可以在 C 中使用 C++ classes。您可以通过接口在 C 中使用 C++ 模块。 stackoverflow.com/questions/11971063/how-to-use-c-objects-in-c
  • 那么extern "C" CAdWrksSession gAdWrksSession;如何与类类型一起工作?
  • 我真的不知道。

标签: c++ xcode c++11 extern linkage


【解决方案1】:

如果 CAdWrksSession 真的是一个类而不是一个不透明的指针,我认为您在标头中使用的extern "C" 将被忽略。在this 堆栈溢出问题中有一些关于extern "C" 行为的讨论。

确保你的头文件确实是 C 的唯一方法是将头文件包含在一个虚拟的 main.c 中,并尝试将库与它链接起来。 (如果您想对此进行更多说明,请告诉我)

但是,也许我们可以找到另一种方法来解决您的问题。我不知道你对这个插件有什么限制。我建议您创建一个代理库,它是一个共享对象,它与遗留代码私下链接(如果可能的话也静态链接)。也就是说,将代理设计模式see API section book 3.4.1 应用于您需要公开的所有类。

然后你可以用这个代理库建立新的代码链接,这样你就不会发生名称冲突。

【讨论】:

  • CAdWrksSession 确实是一个类,但 extern "C" 并没有被忽略。删除它会产生许多错误,并使其成为没有外部链接的普通对象会显示数百个 duplicate 警告。我终于做到了static,现在它工作得很好。
猜你喜欢
  • 2017-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 2016-09-18
  • 2017-02-12
相关资源
最近更新 更多