CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Feb 2007
    Posts
    5

    Reflection - Assembly::CreateInstance of a non "ref" c++ class

    Hello All.
    I have a c++ class not defined with the ref keyword

    class CMsg {...}

    I'm trying to create an instance of CMsg using Reflection, as follows:
    Assembly^ assembly = Assembly::GetAssembly(CMsg::typeid);
    System::Object^ msg = assembly->CreateInstance("SIMsgs.CMsg");

    Well, it works, I get a CMsg, but as a _reference_, while I need a pointer....
    Since CMsg is not a "ref" class I can't cast the return value to CMsg, and so can't call its methods. I can see it's member in the debugger, but can't reach them.

    For example this line:
    CMsg ^cmsg = (CMsg ^)msg;

    Create the following complication errors:
    Error 1 error C3699: '^' : cannot use this indirection on type 'SIMsgs::CMsg' e:\projects\Secure1\pkg\Server\SIMsgs\MsgGenerator.cpp 34
    Error 2 error C3699: '^' : cannot use this indirection on type 'SIMsgs::CMsg' e:\projects\Secure1\pkg\Server\SIMsgs\MsgGenerator.cpp 34
    Error 3 error C2440: 'type cast' : cannot convert from 'System::Object ^' to 'SIMsgs::CMsg *' e:\projects\Secure1\pkg\Server\SIMsgs\MsgGenerator.cpp 34

    Anyway to get a (CMsg *) out of the return value of CreateInstance()?
    Any other solution?

    Thank you very much and in advance,
    Roee Oz

  2. #2
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    If a class isn't managed, you can't use reflection on it. What you're getting is strange behaviour : but I really, really wouldn't go any further with this without making the class managed.

    Darwen.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  3. #3
    Join Date
    Feb 2007
    Posts
    5

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    Thanks for your answer. I already converted the code not to use reflection, but I would still want to understand better what happens here since my application mixing managed and unmanged code as well as C# and C++. As so I would like to improve my understanding of the CreateInstance mechanisem, reference types, pointer types and so on.
    I'll still be glad if someone can explain this funny behavior (CreateInstance() initialize a non managed class as a reference, which I can't use)
    Roee

  4. #4
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    Chances are that you have some managed code inside of your native class. This creates a kind of hybrid : it's not a real managed class, it's sort of half managed.

    I've noticed this sort of behaviour before and it is rather peculiar. I've never gone into the exact mechanisms behind it : let's face it you shouldn't be doing it anyway.

    What's probably happening is that a managed wrapper around the native class is being created when you call CreateInstance(). Probably the same sort of thing as the COM mechanism (CCW/RCWs).

    Darwen.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  5. #5
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    I've just tried this :

    Code:
    #include "stdafx.h"
    
    using namespace System;
    using namespace System::Reflection;
    using namespace System::Runtime::InteropServices;
    
    class CMyClass
    {
    public:
       CMyClass()
       {
          m_nData = 100;
    
          System::Diagnostics::Debug::WriteLine("Constructed");
       }
       
       void Trace()
       {
          System::Diagnostics::Debug::WriteLine("Trace"));
       }
       
    private:
       int m_nData;
    } ;
    
    int main(array<System::String ^> ^args)
    {
        Assembly ^assembly = Assembly::GetExecutingAssembly();
        Object ^obj = assembly->CreateInstance("CMyClass");
        System::Diagnostics::Debug::WriteLine(obj->GetType());
        
        GCHandle handle = System::Runtime::InteropServices::GCHandle::Alloc(obj, GCHandleType::Pinned);
        CMyClass *pMyClass = reinterpret_cast<CMyClass *>(handle.AddrOfPinnedObject().ToPointer());
        pMyClass->Trace();
        handle.Free();
        return 0;
    }
    It appears that the memory for the class is being allocated, but the constructor isn't being called. After pinning the memory and recasting you can make method calls to the class, but this could just be luck.

    Darwen.
    Last edited by darwen; February 20th, 2007 at 08:59 AM.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  6. #6
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    Ah ha ! How's this for an explanation :

    The C++ class is being defined as an empty managed structure, but with the size of the structure defined as the size of the C++ class (therefore the memory is being allocated correctly).

    If you use Lutz Roeder's .NET reflector to look at the class then you'll see it's being defined as :

    Code:
    [StructLayout(LayoutKind.Sequential, Size=4), NativeCppClass, DebugInfoInPDB, MiscellaneousBits(0x40)]
    internal struct CMyClass
    {
    }
    So the metadata for creating the memory for the class exists, but not the metadata of the methods/properties/fields etc of the class.

    Darwen.
    Last edited by darwen; February 20th, 2007 at 09:01 AM.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  7. #7
    Join Date
    Feb 2007
    Posts
    5

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    Hay, didn't monitor this thread for a while.
    Great answer and explanation, thanks a lot.
    I didn't look at it since the "Just Don't Do It" discussion.

    Thanks again for the explanations.

    Roee

  8. #8
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Reflection - Assembly::CreateInstance of a non "ref" c++ class

    Quote Originally Posted by darwen View Post
    Ah ha ! How's this for an explanation :

    The C++ class is being defined as an empty managed structure, but with the size of the structure defined as the size of the C++ class (therefore the memory is being allocated correctly).

    So the metadata for creating the memory for the class exists, but not the metadata of the methods/properties/fields etc of the class.

    Darwen.
    Exactly correct. You can then use "placement new" to actually create the native object inside that space

    The use-cases where this is a desirable approach are pretty slim, but are NOT zero.....

    Just think of it as another custom allocator mechanism (something C++ heavily supports!)
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured