我有一个使用VS2010 C#构建的简单.NET dll,它暴露了一个类的2个静态成员
public class Polygon
{
public static void Test(int test) {}
public static void Test(List<int> test) {}
}
然后我从VS2010 C ++创建了一个Console应用程序,并在_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> ]
我的一些观察结果:
Test(List<int> test)
重命名为Test2(List<int> test)
我的问题是,出了什么问题以及如何从C ++方面解决它。
我目前的解决方法是在C#中重命名该方法,但我宁愿不必这样做,我觉得我的C ++项目中可能缺少一个设置。
编辑:
我在C ++中找到了一个更好的解决方法,看起来我可以将.NET调用包装在另一个函数中。
void wrapper()
{
Polygon::Test(3);
}
extern "C" void TestMe()
{
wrapper();
}
要做到这一点似乎很愚蠢,我想知道它是否是编译器错误?让我感到害怕的是使用这样的方法,不得不担心C#开发人员可能会在以后添加这样的静态方法并打破C ++构建。
答案 0 :(得分:3)
我将在这里拍摄一个疯狂的镜头,原因如下:
在编译期间,MSVC的C ++编译器看到extern "C" function
TestMe()
在类Test()
内调用函数Polygon
。 Polygon
是编译器的不完整类型。我想编译器无法看到函数Polygon::Test(3)
是返回一个不完整的类型还是返回任何内容,它决定它需要在那个时候返回一个错误,以防该类型变成一个普通的C-风格POD类型。
上述似乎是MSVC的一个合理假设,因为(7.5 / 9“链接规范”)C ++标准说:
“从C ++到其他语言定义的对象以及用其他语言在C ++中定义的对象的链接是实现定义的和语言相关的。只有在两种语言实现的对象布局策略足够相似的情况下才能实现这种联系实现。“
这可以解释一旦删除extern C
链接规范或将调用替换为Cstyle函数后错误消失。