【问题标题】:C linkage function cannot return C++ class - error resulting from the contents of my methodC 链接函数无法返回 C++ 类 - 我的方法内容导致的错误
【发布时间】:2014-03-08 00:38:23
【问题描述】:

我正在导出一个可以从非托管代码调用的方法,但该函数本身存在于托管 c++ 项目中。以下代码导致编译器错误:

error C2526: 'System::Collections::Generic::IEnumerator<T>::Current::get' : C linkage function cannot return C++ class 'System::Collections::Generic::KeyValuePair<TKey,TValue>'
error C2526: 'System::Collections::Generic::Dictionary<TKey,TValue>::KeyCollection::GetEnumerator' : C linkage function cannot return C++ class 'System::Collections::Generic::Dictionary<TKey,TValue>::KeyCollection::Enumerator'

extern "C"
__declspec( dllexport )
bool MyMethod(std::string &name, std::string &path, std::map<std::string, std::string> &mymap)
{
  System::Collections::Generic::Dictionary<System::String ^, System::String^> _mgdMap = gcnew System::Collections::Generic::Dictionary<System::String ^, System::String ^>();

  // Blah blah processing
}

稍微研究一下这个错误,问题通常与标记为“extern "C"”的方法的定义有关。那么它为什么要关心方法内部发生的事情呢?

如果我将 Dictionary 初始化注释掉,或者将其切换为 HashTable,那么一切都会很好地编译。

以下方法也有效 - 如果不是在本地定义字典,而是通过在方法中初始化它来避免局部变量。

bool status = CallAnotherMethod(ConvertToDictionary(mymap));

其中 ConvertToDictionary 声明为

System::Collections::Generic::Dictionary<System::String ^, System::String ^>^ ConvertToDictionary(std::map<std::string, std::string> &map)
{
}

这告诉我这是一个看似任意的错误。我仍然想了解为什么编译器认为这是一个问题。

【问题讨论】:

  • 你能解决这个问题吗?似乎我有类似的问题 - 无法从 C++/CLI 初始化 C# 类,我相信这是因为“extern C”要求编译器在创建字典或类之前知道它的大小,这是“ C" 语言 - 接口先于实现,它告诉编译器这个对象需要初始化多少内存,Hans Passant 在这里回答了 stackoverflow.com/questions/2718836/…
  • 问题是我的类是用 C# 定义的,我不想在 C++/CLI 中复制它的实现 - 我如何告知 C++/CLI 这个类需要什么大小?

标签: c++ extern managed-c++ linkage vc90


【解决方案1】:

对不起,我需要与某人分享我的快乐:)

似乎您可以通过创建两个包装器来解决这个问题 - 一个用于标记为“extern C”的外部调用,一个用于内部调用。在这种情况下,“extern C”之外的所有内容都将像往常一样执行 .NET 代码。

这里的topicstarter回答了 - C++/CLI->C# error C2526: C linkage function cannot return C++ class

void DummyInternalCall(std::string &name, std::string &path, std::map<std::string, std::string> &mymap)
{
   System::Collections::Generic::Dictionary<System::String ^, System::String^> _mgdMap =  gcnew System::Collections::Generic::Dictionary<System::String ^, System::String ^>();

  // Blah blah processing
}

extern "C" __declspec( dllexport )
bool MyMethod(std::string &name, std::string &path, std::map<std::string, std::string> &mymap)
{
   DummyInternalCall(name, path, mymap);
}

【讨论】:

  • 是的,这也是我在问题中所说的。这似乎不太合乎逻辑,但确实有效。看看你链接的问题,我想那里的解释是有道理的。
【解决方案2】:

如果你用 C++ 编写一个要从 C 调用的函数,你不能在它的接口(参数和返回类型)中使用 anything,这不是纯 C。参数是 C++ 对象。

【讨论】:

  • 没有任何 std:: 参数导致编译错误。这不是问题。
  • @Liz:那么你的编译器可能在其他地方出错了。 您不能在extern "C" 链接函数原型中使用 C++ 构造。 例如所有这些引用:您将如何从用 C 编写的编译单元传递那些? C 不知道引用。
猜你喜欢
  • 1970-01-01
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2018-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多