locked
Static method on a C++/CX base class throws MissingMethodException in C#

    Question

  • Hi,

    I'm using C++/CX to create some ref class components to expose into .Net. I have a a small class hierarchy and I'd like some static helper methods on the base class to be used in .Net (a "factory method" type of thing). However calling for static methods on the base class throw MissingMethod exception. On the derived classes the static method call works fine. Any ideas how to resolve this? Is this a bug?

    Here's a simple reproducer first the C++/Cx code 

    	public ref class MyBaseClass
    	{
    	public:
    		static void TestStaticOnBase() { };
    		// other methods
    	protected private:
    		MyBaseClass() { } // base class needs constructor hidden from .Net
    	};
    
    
    	public ref class MyDerivedClass sealed : public MyBaseClass
        {
    	public:
    		static void TestStaticOnDerived() { };
    		// other methods
    		MyDerivedClass() { }
        };
    

    Then in C#

                MyDerivedClass.TestStaticOnDerived(); // Works ok
    
                MyBaseClass.TestStaticOnBase();  // throws missing method exception
    

    I'm using RC version of VS2012 and Win8.

    Thanks,

      Chris,

     

    Wednesday, August 1, 2012 12:33 PM

Answers

  • I think I've got an answer to these questions and this issue. Since the RTM the compiler checking of ref class has been tightened up a lot and the example above no longer compiles. The result is to be a base class it must derive from a base class like Windows::UI::Xaml::DependencyObject

    which is not so good for my scenario because it ties the classes to the UI thread and I need these objects to be accessible from any thread (and not dependency objects).

    http://msdn.microsoft.com/en-us/library/windows/apps/hh699870.aspx

    Indecently when you do this static methods do work on the base class.

    The only other alternative I can see is to use an public interface instead of a base class and this is what I've gone for to make some progress.

    Cheers,

      Chris.

    Thursday, August 23, 2012 11:26 AM

All replies

  • Here's what I think:

    Officially, the class needs to be sealed to be exposed to RT. Since your base class is not sealed (it can't be since it's acting as a base) it won't be properly exposed to WinRT callers. That would explain why its static methods are not callable.


    http://blog.voidnish.com



    Wednesday, August 1, 2012 12:41 PM
  • That said, it's rather inconsistent to expose the class but not expose the static methods. But then this is a new compiler, so such things should be expected.

    http://blog.voidnish.com

    Wednesday, August 1, 2012 12:46 PM
  • I was assuming (hoping) as long as public constructor was hidden from .Net I could get some small hierarchy present with a base class (so can't be sealed). From the MSDN doc ...

    "One important aspect of inheritance in C++/CX is that the consuming code is not allowed to derive new classes from publicly constructable types. Therefore, only sealed classes can have public constructors."

    In this case I could change the API to move the static method off to some other class, but its always nice to have them on the classes they relate to.

    Wednesday, August 1, 2012 12:54 PM
  • Hi, maybe this thread can help you.

    • Edited by t-n-x Wednesday, August 1, 2012 1:16 PM
    Wednesday, August 1, 2012 1:15 PM
  • Yeah, I agree that it's cleaner to have them in the right classes. But remember that previously COM did not have any concept of static methods, so they had to do a fair bit of plumbing to get static methods working. What's interesting is that a non-sealed class is visible to RT callers. To me, that's not right that the class is visible but a static method on the class is not.

    http://blog.voidnish.com


    Wednesday, August 1, 2012 1:20 PM
  • Calling non-static methods seemed to work fine whether it came from the derived or base class (in my limited testing) as long as there's no public constructors on the base class. That seems an ok compromise yet still allowing an some inheritance (within C++/CX) to exist.

    If you try and "new" in C# of a C++/CX base class you get intellisense error saying its got no constructor. Same if you try and derive from it. For my API situation that's ok, but living without inheritance would be pretty rough.

    Wednesday, August 1, 2012 2:18 PM
  • It would be good to get some clarity on this issue from Microsoft guys following on from Nish's comment.

    Do all public C++\C classes have to be sealed? I really hope not for base classes and the MSDN doc also implies they don't have to be sealed as long as constructors are hidden from .Net.

    Is the issue with static method on a base class not working in .Net a restriction of C++/Cx projection into .Net ie a known limitation? I could live with it and move the statics onto another class. Is this limitation captured anywhere and/or would it ever get fixed?

    thanks,

      Chris.

    Friday, August 3, 2012 10:00 AM
  • Hello,

    I just wanted to let you know that I am looking into this for you. Unfortunately I haven't been able to locate an authoritative source yet but I will continue to see what I can dig up. I hope to get back to you early next week.

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Saturday, August 4, 2012 12:11 AM
    Moderator
  • I think I've got an answer to these questions and this issue. Since the RTM the compiler checking of ref class has been tightened up a lot and the example above no longer compiles. The result is to be a base class it must derive from a base class like Windows::UI::Xaml::DependencyObject

    which is not so good for my scenario because it ties the classes to the UI thread and I need these objects to be accessible from any thread (and not dependency objects).

    http://msdn.microsoft.com/en-us/library/windows/apps/hh699870.aspx

    Indecently when you do this static methods do work on the base class.

    The only other alternative I can see is to use an public interface instead of a base class and this is what I've gone for to make some progress.

    Cheers,

      Chris.

    Thursday, August 23, 2012 11:26 AM
  • Thanks for following up,

    We have subtly tweaked ref classes between RP and RTM. There are still some outstanding questions such as how to deal with virtual methods in ref classes, etc. My team is working to try and understand the intent as well as the logic behind these subtle but important scenarios. Hopefully over the next few months through blogs and forum posts things will get more clear.

    Thanks for your patience,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Friday, August 24, 2012 9:34 PM
    Moderator