【问题标题】:extern "C" has no effect in msvc++ 9.0extern "C" 在 msvc++ 9.0 中无效
【发布时间】:2010-03-17 16:52:51
【问题描述】:

我为两个编译器管理 JNI 项目:MSVC++ 8.0 和 9.0, 我的 cpp 文件包含以下实现: 外部“C”{ JNIEXPORT jlong​​ JNICALL Java_context_ServiceProviderContext_StartServiceProvider (JNIEnv * env, jclass, jstring jspath){ ...... }

在depends.exe 实用程序的帮助下,我可以看到MSVC 8.0 按预期成功导出函数:Java_context_ServiceProviderContext_StartServiceProvider 但是在 MSVC 9.0 下编译让我发疯了,它的导出就像完全忽略 extern "C" 一样。 depends.exe 显示:_Java_context_ServiceProviderContext_StartServiceProvider@12

有人知道 9.0 项目中究竟是什么导致了这种行为吗?

【问题讨论】:

  • 技术描述是您的 9.0 编译是名称修改。 C 没有命名混乱(这是Extern C 告诉编译器执行的操作的一部分)。
  • @Paul Nathan - 那么,你的建议是什么?
  • 我没有真正的答案给你。它听起来像一个错误。现在需要声明那个或一个标志......我唯一能想到的就是在 MSDN 上翻找和/或致电 Microsoft 支持。

标签: c visual-c++ extern visual-c++-2008 name-decoration


【解决方案1】:

JNICALL 可能是#define JNICALL __stdcall。更改调用约定将修复名称修饰,但会严重(包括静默)破坏 JNI,因为它将调用一个假设为 __stdcall 的函数并获得其他内容。

它真的不起作用吗?从我可以谷歌的内容来看,JVM 似乎知道如何正确地装饰函数名称。

【讨论】:

  • 你是对的,它是 __stdcall,但 JVM 期望的正是 Java_context_ServiceProviderContext_StartServiceProvider。请注意,在 MSVC 8.0 下一切都是正确的,我很确定在迁移项目时会出现问题。
【解决方案2】:

这是 __stdcall 调用约定;你需要__cdecl。也许尝试将 __cdecl 添加到您的函数定义中?

或者,更改项目设置中的默认调用约定。

【讨论】:

  • 不,谢谢 - JNI 完全期望 __stdcall。并且 8.0 管理它没有任何问题。只是为了您的信息 __cdecl 和 __stdcall 之间的区别不是装饰,而是参数的顺序。
  • __cdecl 和 __stdcall 之间的唯一区别是谁负责将参数从堆栈中弹出。但是,是的,调用约定和名称装饰是相互正交的。
  • +1。我投票赞成,因为它为我解决了问题。在我删除 __stdcall 并让默认的 __cdecl 项目设置启动之前,我的带有 extern "C" 的 dll-export 被破坏了。如果在这种情况下调用约定本身实际上不是解决方案的本质,那么可能是另一个评论员想发布一个新的答案,以阐明为什么这是有效的。
猜你喜欢
  • 2019-12-22
  • 2022-06-17
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多