Функция связывания C не может вернуть класс C++ - ошибка, возникающая из-за содержимого моего метода

Я экспортирую метод, который можно вызвать из неуправляемого кода, но сама функция живет в управляемом проекте 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 ''. Так почему это вообще касается того, что происходит внутри метода?

Если я закомментирую инициализацию словаря или переключу ее на HashTable, все будет прекрасно скомпилировано.

Следующее также работает - если вместо определения словаря локально, я избегаю локальной переменной, инициализируя ее в методе.

bool status = CallAnotherMethod(ConvertToDictionary(mymap));

где ConvertToDictionary объявлен как

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

Что говорит мне, что это, казалось бы, произвольная ошибка. Я все еще хотел бы понять, почему компилятор считает, что это проблема.

2 ответа

Решение

Извините за некропост, но мне нужно поделиться своим счастьем с кем-то:)

Кажется, что вы можете решить эту проблему, просто создав две оболочки - одну для внешнего вызова, помеченную "extern C", и одну для внутреннего вызова. В этом случае все, что находится за пределами "extern C", будет выполняться как обычный код.NET.

На это ответил автор темы - ошибка C++/CLI->C# C2526: функция связи C не может вернуть класс C++

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);
}

Если вы пишете в C++ функцию, которая должна вызываться из C, вы не можете использовать в ее интерфейсе что-либо (аргументы и тип возвращаемого значения), что не является простым C. Здесь все ваши аргументы являются объектами C++.

Другие вопросы по тегам