Home Dashboard Directory Help
Search

Base class method build with the Visual Studio 2012 C++/CLR compiler fails to call the correct overriden virtual function by VBA Derks


Status: 

Closed


1
0
Sign in
to vote
Type: Bug
ID: 774800
Opened: 12/19/2012 2:57:44 PM
Access Restriction: Public
2
Workaround(s)
view
0
User(s) can reproduce this bug

Description

A .NET assembly created with the Visual Studio 2012 C++/CLR compiler (11.0.51106.01) fails to call the correct virtual override function. A non virtual function calls the base class method implementation while it should call the derived method. This defect becomes visible when the base class and the derived class are in different assemblies and the return type is a native C++ pointer.
Building the assemblies with the Visual Studio 2010 SP1 C++/CLR compiler gives the expected result.
Merging the base and derived class in one assembly gives the expected result.

=== Code Assembly Base.DLL ====
__interface IStorageConnect;

namespace Company { namespace EA { namespace Base {

public value struct IStorageConnect2
{
};

public ref class Base
{
public:
    void Init();
    virtual IStorageConnect* Bad();
    virtual IStorageConnect2* Good();
};
}}}

#include "Base.h"
#include "IStorageConnect.h"

using namespace System;
using namespace Company::EA::Base;

#pragma make_public(IStorageConnect)


void Base::Init()
{
    Bad();
    Good();
}

IStorageConnect* Base::Bad()
{
    Console::WriteLine(L"Base.Bad");
    return 0;
}

IStorageConnect2* Base::Good()
{
    Console::WriteLine(L"Base.Good");
    return 0;
}

== Code Assembly Derived.DLL ===
public ref class Derived : Base
{
public:
    virtual IStorageConnect* Bad() override
    {
        Console::WriteLine(L"Derived.Bad");
        return 0;
    }

    virtual IStorageConnect2* Good() override
    {
        Console::WriteLine(L"Derived.Good");
        return 0;
    }
};

int main(array<System::String ^> ^)
{
    auto obj = gcnew Derived();
    obj->Init();

    Console::ReadKey();
    return 0;
}

The expected console ouput is (and the output if build with VS2010):
Derived.Bad
Derived.Good

The console output if build with VS2012 is:
Base.Bad
Derived.Good

Both executables running on .NET 4.5

The root cause seems to be the fact that VS2012 generates a different .NET definition for the native C++ interface pointer that is added to the global namespace. The same definition is generated in both assemblies. VS2012 generates a different definition then VS2010.
Code generated by VS2010 is seen by .NET as identical but code generated by VS2012 is seen as different types. This causes the .NET runtime to assume that the override doesn't match the base class method signature and will not call it.
Details
Sign in to post a comment.
Posted by Microsoft on 2/5/2013 at 10:47 AM
Hi:
    Thanks for reporting the issue.
    A fix for this issue has been checked into the compiler sources. The fix should show up in the next release of Visual C++.

Xiang Fan
Visual C++ Team
Posted by Microsoft on 12/20/2012 at 12:36 AM
Thank you for submitting feedback on Visual Studio and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by Microsoft on 12/19/2012 at 3:51 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
Posted by Vapour in the Alley on 1/2/2013 at 4:08 AM
Another workaround is to remove the "#pragma make_public(IStorageConnect)".
To get things working adjust the return type of the virtual method to void* and perform subsequent upcasts in the calling code.
Posted by VBA Derks on 12/19/2012 at 3:07 PM
workaround is to not use a native C++ pointer as return type but a pointer to an explicit public value struct (as done in the sample code).
File Name Submitted By Submitted On File Size  
VirtualOverrideProblem.zip 12/19/2012 10 KB