【问题标题】:Mangled name even after extern c即使在 extern c 之后,名称也会被破坏
【发布时间】:2014-07-24 10:02:46
【问题描述】:

我在我的 C# 项目中包含了一个 C++ 库,我正在调用它的方法之一。

早些时候我遇到了修改问题,然后阅读了有关 extern c 并将其应用于 C++ 方法。

然后尝试如下调用它:

[DllImport(@"F:\bin\APIClient.dll")]
public static extern IntPtr logIn2(IntPtr a, IntPtr b, IntPtr c, IntPtr d, IntPtr e, IntPtr f, int g);

但我仍然收到入口点异常。

C++:

 APICLIENT_API char* logIn2(const char* a, const char* b,const char* c,const char* d,const char* e,const char* f, int g);

如果我在 DLLImport 中使用 entryPoint,那么它工作正常:

[DllImport(@"F:\bin\APIClient.dll", EntryPoint = "?logIn2@CAPIClient@API@@QAEPADPBD00000H@Z", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr logIn2(IntPtr a, IntPtr b, IntPtr c, IntPtr d, IntPtr e, IntPtr f, int g);

为什么即使在使用 extern c 之后,我也必须提供这个入口点才能使事情正常工作。

【问题讨论】:

  • 你能展示一下 C++ 方法声明吗?
  • 您是否只在头文件中使用 extern c?从您所说的看来,您似乎在标头中声明为 extern C,但该对象仍然在 .cpp 中编译为 cpp (因此被破坏)。尝试打开 dll,看看你的 C 原型是否暴露。
  • @MichaelCMS:: 可以在类方法中使用外部“C”吗?如果我们在标头中使用 extern C 则会出错。所以我们在实现中使用它。
  • @jeroenh 我已经更新了问题。
  • 你说的是类方法吗?类方法名称总是错位的。

标签: c# c++ dllimport


【解决方案1】:

修饰的 C++ 名称不是问题。这实际上是非常可取的,当 C++ 代码更改和函数签名更改时,它会自动使您不必诊断非常困难的运行时崩溃。由于现在会出现不匹配,并且您会收到一个简单的“找不到过程”错误消息,而不是完全无法诊断的损坏的调用堆栈。

很多更大的问题,以及extern "C" 不起作用的原因是这是CAPIClient 类的实例方法。它使用 __thiscall 调用约定,需要传递一个有效的 this 指针。您无法从 pinvoke 中获得它,它需要为 C++ 对象分配内存并调用 CAPIClient 构造函数。只有 C++ 编译器知道如何正确地做到这一点,只有它知道要分配的正确内存量。所以你不能pinvoke,你必须写一个C++/CLI wrapper。

当您调用 C++ 类的实例方法时,通常会发生硬崩溃,通常报告为 AccessViolationException。当实例方法尝试通过无效的 this 指针访问 C++ 类的另一个其他实例成员时触发。只能正确调用静态 C++ 函数。由于您似乎还没有触发异常,因此有一些提示表明该函数首先应该是 static 的。

【讨论】:

  • C++ 方法不是静态的,是的,当我们在调用的 C++ 方法和其他类方法中编写任何代码时,Visual Studio 会崩溃。
  • 不,崩溃的不是 Visual Studio。这是你的 C++ 代码。现在应该有点明显了。否则通过启用非托管代码调试很容易看到。我已经给你答案了,你必须编写一个 C++/CLI 包装器,这样你才能正确地构造 C++ 对象。
  • 正如您所说“只有静态 C++ 函数才能正确调用。”现在我们已将 C++ 的方法设为静态,但问题仍然存在。
猜你喜欢
  • 2012-09-07
  • 1970-01-01
  • 2022-11-03
  • 1970-01-01
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多