C++/CLI-> C#错误C2526:C连接函数无法返回C++类

Pes*_*nat 9 c# c++-cli visual-studio-2010 extern linkage

我有一个使用VS2010 C#构建的简单.NET dll,它暴露了一个类的2个静态成员

public class Polygon
{
    public static void Test(int test) {}
    public static void Test(List<int> test) {}
}
Run Code Online (Sandbox Code Playgroud)

然后我从VS2010 C++创建了一个Console应用程序,并在_tmain上面添加了这个函数

extern "C" void TestMe()
{
    Polygon::Test(3);
}
Run Code Online (Sandbox Code Playgroud)

添加引用和编译会给我这个错误

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>          ]
Run Code Online (Sandbox Code Playgroud)

我的一些观察:

  • 如果我删除extern"C",它编译成功
  • 如果我重命名Test(List<int> test),它会成功编译Test2(List<int> test)

我的问题是,出现了什么问题以及如何从C++方面解决它.

我目前的解决方法是在C#中重命名该方法,但我宁愿不必这样做,我觉得我的C++项目中可能缺少一个设置.

编辑:

我在C++中找到了一个更好的解决方法,看起来我可以将.NET调用包装在另一个函数中.

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

extern "C" void TestMe()
{
    wrapper();
}
Run Code Online (Sandbox Code Playgroud)

这样做似乎很愚蠢,我想知道它是否是一个编译器错误?令我害怕的是使用这样的方法,并且不得不担心C#开发人员可能稍后添加这样的静态方法并打破C++构建.

Alo*_*ave 6

我只是想在这里大胆尝试,理由如下:

在编译期间 MSVC 的 C++ 编译器看到extern "C" function TestMe()正在调用Test()类中的函数PolygonPolygon是编译器的不完整类型。我猜编译器看不到函数Polygon::Test(3)返回的是不完整的类型还是返回任何东西,它决定在那个时候需要返回一个错误,以防该类型不是普通的 C 风格的 POD 类型。

以上似乎是 MSVC 部分的合理假设,如 C++ 标准 (7.5/9“链接规范”) 所述:

“从 C++ 到其他语言定义的对象以及从其他语言到 C++ 定义的对象的链接是实现定义和语言相关的。只有当两种语言实现的对象布局策略足够相似时,才能实现这种链接。”

这将解释一旦删除extern C链接规范或替换对 Cstyle 函数的调用,错误就会消失。