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" functionTestMe()is calling an functionTest()inside a classPolygon.Polygonis 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 Clinkage specification or replace the call to a Cstyle function.