I have a simple .NET dll built with VS2010 C# that exposes 2 static members of a class
public class Polygon
{
public static void Test(int test) {}
public static void Test(List<int> test) {}
}
I then created a Console app from VS2010 C++ and added this function above _tmain
extern "C" void TestMe()
{
Polygon::Test(3);
}
Adding the reference and compiling gives me this error
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> ]
Some of my observations:
- It compiles successfully if I remove extern "C"
- It compiles successfully if I rename
Test(List<int> test)
toTest2(List<int> test)
My question is, what is going wrong and how to fix it from the C++ side.
My current workaround is to rename the method in C#, but I would rather not have to do this, I have a feeling there is a setting I might be missing in my C++ project.
Edit:
I found a better workaround in the C++, it looks like I can wrap the .NET calls in another function.
void wrapper()
{
Polygon::Test(3);
}
extern "C" void TestMe()
{
wrapper();
}
It seems silly to have to do this, I'm wondering if it's a compiler bug? What scares me is using such methods and having to worry that the C# developer may at a later point add such a static method and break the C++ builds.
I am just going to take a wild shot here, with the following reasoning:
During compilation MSVC's C++ compiler sees the
extern "C" function
TestMe()
is calling an functionTest()
inside a classPolygon
.Polygon
is an incomplete type for the compiler. I guess the compiler cannot see whether the functionPolygon::Test(3)
is returning an incomplete type or returning anything at all, it decides that it needs to return an error at that point in case the type turns out to not be a plain C-style POD type.The above seems a reasonable assumption on part of MSVC as in (7.5/9 "Linkage specifications") the C++ standard says:
"Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved."
That would explain the error vanishing once you remove the
extern C
linkage specification or replace the call to a Cstyle function.