C ++ / CLI-> C # ошибка C2526: функция связи C не может вернуть класс C ++ - PullRequest
9 голосов
/ 16 июня 2011

У меня есть простая .NET dll, созданная на VS2010 C #, которая предоставляет 2 статических члена класса

public class Polygon
{
    public static void Test(int test) {}
    public static void Test(List<int> test) {}
}

Затем я создал консольное приложение из VS2010 C ++ и добавил эту функцию выше _tmain

extern "C" void TestMe()
{
    Polygon::Test(3);
}

Добавление ссылки и компиляция дает мне эту ошибку

1>WierdError.cpp(9): error C2526: 'System::Collections::Generic::List<T>::GetEnumerator' : C linkage function cannot return C++ class 'System::Collections::Generic::List<T>::Enumerator'
1>          with
1>          [
1>              T=int
1>          ]
1>          WierdError.cpp(9) : see declaration of 'System::Collections::Generic::List<T>::Enumerator'
1>          with
1>          [
1>              T=int
1>          ]
1>          WierdError.cpp(9) : see reference to class generic instantiation 'System::Collections::Generic::List<T>' being compiled
1>          with
1>          [
1>              T=int
1>          ]

Некоторые из моих наблюдений:

  • Успешно компилируется, если я удаляю extern "C"
  • Успешно компилируется, если я переименую Test(List<int> test) в Test2(List<int> test)

У меня вопрос: что идет не так и как это исправить со стороны C ++.

Мой текущий обходной путь - переименовать метод в C #, но я бы предпочел не делать этого, у меня есть ощущение, что есть настройка, которую я мог бы пропустить в своем проекте C ++.

Edit:

Я нашел лучший обходной путь в C ++, похоже, я могу обернуть вызовы .NET в другую функцию.

void wrapper()
{
    Polygon::Test(3);
}

extern "C" void TestMe()
{
    wrapper();
}

Кажется глупым делать это, мне интересно, это ошибка компилятора? Меня пугает использование таких методов и необходимость беспокоиться о том, что разработчик C # может позже добавить такой статический метод и нарушить сборки C ++.

1 Ответ

3 голосов
/ 16 июня 2011

Я просто собираюсь сделать дикий выстрел здесь, со следующими рассуждениями:

Во время компиляции компилятор MSVC C ++ видит, что extern "C" function TestMe() вызывает функцию Test() внутри класса Polygon.Polygon - это неполный тип для компилятора.Я предполагаю, что компилятор не может видеть, возвращает ли функция Polygon::Test(3) неполный тип или вообще что-либо возвращает, он решает, что ему нужно вернуть ошибку в тот момент, если тип оказывается не простым POD в стиле Ctype.

Вышеизложенное кажется разумным допущением для части MSVC, поскольку в (7.5 / 9 "Спецификации связи") стандарт C ++ гласит:

"Связь с C ++ с определенными объектамив других языках и для объектов, определенных в C ++, из других языков определяется реализацией и зависит от языка. Только в тех случаях, когда стратегии компоновки объектов двух реализаций языка достаточно похожи, такая связь может быть достигнута. "

Это объясняет исчезновение ошибки после удаления спецификации связи extern C или замены вызова функции Cstyle.

...