Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Managed C++/CLI
  4. Managed & Unmanaged type problem;

Managed & Unmanaged type problem;

Scheduled Pinned Locked Moved Managed C++/CLI
c++helpquestion
9 Posts 2 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Lost User
    wrote on last edited by
    #1

    I'm living a trouble with managed c++ that below code doesn't work properly so it has generated following error; test.cpp(25) : error C2440: '=' : cannot convert from 'classB __gc *' to 'void *' Cannot convert a managed type to an unmanaged type Code at following; typedef struct { void* memberA; } classA; typedef struct { int int_memberB; char* cp_memberB; } classB; __gc class ManagedClass { private: classA m_classA; classB m_classB; public: ManagedClass() { m_classA.memberA = &m_classB; } virtual ~ManagedClass() { } }; How can i solve that problem? Some must watch while some must sleep... OGED

    J 1 Reply Last reply
    0
    • L Lost User

      I'm living a trouble with managed c++ that below code doesn't work properly so it has generated following error; test.cpp(25) : error C2440: '=' : cannot convert from 'classB __gc *' to 'void *' Cannot convert a managed type to an unmanaged type Code at following; typedef struct { void* memberA; } classA; typedef struct { int int_memberB; char* cp_memberB; } classB; __gc class ManagedClass { private: classA m_classA; classB m_classB; public: ManagedClass() { m_classA.memberA = &m_classB; } virtual ~ManagedClass() { } }; How can i solve that problem? Some must watch while some must sleep... OGED

      J Offline
      J Offline
      Jeff J
      wrote on last edited by
      #2

      Ahmet Orkun GEDiK posted: Cannot convert a managed type to an unmanaged type You are trying to keep a pointer to a managed object, in an unmanaged class. Managed objects live on the GC heap, which is not the same as regular heap memory. Locations/pointers to managed stuff can actually change during an app's lifetime (which would invalidate your pointer), and .Net does not update pointers in unmanaged objects, only in managed ones. Although there are ways to coerce .Net to reveal the numeric address of managed objects, it would require pinning the managed object first, then using it for a very short period of time before unpinning it. If not, the GC is prevented from managing its heap properly. It would be more appropriate to get a pointer to a managed object (such as m_classB here) for use by an unmanaged object, as needed, and for no longer. If you could explain how you need to use a managed pointer in an unmanaged context, perhaps I could provide a solution. Cheers

      L 1 Reply Last reply
      0
      • J Jeff J

        Ahmet Orkun GEDiK posted: Cannot convert a managed type to an unmanaged type You are trying to keep a pointer to a managed object, in an unmanaged class. Managed objects live on the GC heap, which is not the same as regular heap memory. Locations/pointers to managed stuff can actually change during an app's lifetime (which would invalidate your pointer), and .Net does not update pointers in unmanaged objects, only in managed ones. Although there are ways to coerce .Net to reveal the numeric address of managed objects, it would require pinning the managed object first, then using it for a very short period of time before unpinning it. If not, the GC is prevented from managing its heap properly. It would be more appropriate to get a pointer to a managed object (such as m_classB here) for use by an unmanaged object, as needed, and for no longer. If you could explain how you need to use a managed pointer in an unmanaged context, perhaps I could provide a solution. Cheers

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #3

        Is that mean we cannot use old libraries or structures? :wtf: Ahmet Orkun GEDiK

        J 1 Reply Last reply
        0
        • L Lost User

          Is that mean we cannot use old libraries or structures? :wtf: Ahmet Orkun GEDiK

          J Offline
          J Offline
          Jeff J
          wrote on last edited by
          #4

          Ahmet Orkun GEDiK wrote: Is that mean we cannot use old libraries or structures? No, unmanaged structures can be used, and in general C++ library routines can be mixed-in with MC++. The catch is in how managed and unmanaged code is used together. Managed data can usually be "marshaled" over to unmanaged stuff, but the way your first post was written, an unmanaged type tried to hold a pointer to a managed object, and for an unknown amount of time. Data from managed objects can be copied over to unmanaged code, but unmanaged code should not try to keep pointers to managed objects around. Only managed code should keep pointers around to other managed objects. In other words, managed code is fairly happy referencing unmanaged data, but it's not so simple the other way around.

          L 1 Reply Last reply
          0
          • J Jeff J

            Ahmet Orkun GEDiK wrote: Is that mean we cannot use old libraries or structures? No, unmanaged structures can be used, and in general C++ library routines can be mixed-in with MC++. The catch is in how managed and unmanaged code is used together. Managed data can usually be "marshaled" over to unmanaged stuff, but the way your first post was written, an unmanaged type tried to hold a pointer to a managed object, and for an unknown amount of time. Data from managed objects can be copied over to unmanaged code, but unmanaged code should not try to keep pointers to managed objects around. Only managed code should keep pointers around to other managed objects. In other words, managed code is fairly happy referencing unmanaged data, but it's not so simple the other way around.

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Ok. Sounds great. But how will i solve my problem ? typdefsampleDlg.cpp(26) : error C2440: '=' : cannot convert from 'SAMPLE __gc *__w64 ' to 'void *' Cannot convert a managed type to an unmanaged type Can you give an example to me ? Ahmet Orkun GEDiK

            J 1 Reply Last reply
            0
            • L Lost User

              Ok. Sounds great. But how will i solve my problem ? typdefsampleDlg.cpp(26) : error C2440: '=' : cannot convert from 'SAMPLE __gc *__w64 ' to 'void *' Cannot convert a managed type to an unmanaged type Can you give an example to me ? Ahmet Orkun GEDiK

              J Offline
              J Offline
              Jeff J
              wrote on last edited by
              #6

              You do not store a managed pointer in an unmanaged object. If you could explain why you wanted to store it, and what it was to be used for, perhaps I could explain a workaround, but without that information, I can't provide a suggestion.

              L 1 Reply Last reply
              0
              • J Jeff J

                You do not store a managed pointer in an unmanaged object. If you could explain why you wanted to store it, and what it was to be used for, perhaps I could explain a workaround, but without that information, I can't provide a suggestion.

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #7

                Ok. I'm using a library that uses standart C++ routines. One function need to assignment such as following; RFC_OPTIONS rfc_option; RFC_CONNOPT_R3ONLY rfc_connopt; rfc_option.connopt = & rfc_connopt; type definitions at below; typedef struct { rfc_char_t * hostname; int sysnr; rfc_char_t * gateway_host; rfc_char_t * gateway_service; } RFC_CONNOPT_R3ONLY; typedef struct { rfc_char_t * destination; RFC_MODE mode; void * connopt; rfc_char_t * client; rfc_char_t * user; rfc_char_t * password; rfc_char_t * language; int trace; } RFC_OPTIONS; So as i metioned, rfc_option.connopt = & rfc_connopt; has generate error. Ahmet Orkun GEDiK

                J 1 Reply Last reply
                0
                • L Lost User

                  Ok. I'm using a library that uses standart C++ routines. One function need to assignment such as following; RFC_OPTIONS rfc_option; RFC_CONNOPT_R3ONLY rfc_connopt; rfc_option.connopt = & rfc_connopt; type definitions at below; typedef struct { rfc_char_t * hostname; int sysnr; rfc_char_t * gateway_host; rfc_char_t * gateway_service; } RFC_CONNOPT_R3ONLY; typedef struct { rfc_char_t * destination; RFC_MODE mode; void * connopt; rfc_char_t * client; rfc_char_t * user; rfc_char_t * password; rfc_char_t * language; int trace; } RFC_OPTIONS; So as i metioned, rfc_option.connopt = & rfc_connopt; has generate error. Ahmet Orkun GEDiK

                  J Offline
                  J Offline
                  Jeff J
                  wrote on last edited by
                  #8

                  One way to do this would be to keep an unmanaged struct around for passing to RfcOpen() calls. I assume you will get your string data as CLR String types, so you might want to keep them around in a .Net/GC struct for convenience, as done here (see m_RfcConnopt). When m_RfcConnopt has been filled, its data can be copied into unmanaged data. In this example the CLR Strings are converted to char strings, and then copied into C++ strings for long-term keeping (optional).

                  using namespace System::Runtime::InteropServices;

                  //a GC struct to hold .Net version of the data, just for convenience here
                  __gc struct RFC_ConOpt
                  {
                  String* sHostName;
                  Int32 sysnr;
                  String* sGatewayHost;
                  String* sGatewayService;
                  };

                  RFC_ConOpt *m_RfcConnopt; //the managed class that holds the connopt stuff
                  std::string sHostName, sGatewayHost, sGatewaySvc; //can be kept in class for storage

                  //Before you call RfcOpen()...

                  IntPtr ptr = Marshal::StringToHGlobalAnsi(m_RfcConnopt->sHostName);
                  sHostName = (char*)ptr.ToPointer(); //store in C++ string (optional)
                  Marshal::FreeHGlobal(ptr); //free temp char string

                  ptr = Marshal::StringToHGlobalAnsi(m_RfcConnopt->sGatewayHost);
                  sGatewayHost = (char*)ptr.ToPointer();
                  Marshal::FreeHGlobal(ptr);

                  ptr = Marshal::StringToHGlobalAnsi(m_RfcConnopt->sGatewayService);
                  sGatewaySvc = (char*)ptr.ToPointer();
                  Marshal::FreeHGlobal(ptr);

                  //get pointers to internal char arrays...
                  rfc_connopt.hostname = &(*sHostName.begin());
                  rfc_connopt.gateway_host = &(*sGatewayHost.begin());
                  rfc_connopt.gateway_service = &(*sGatewaySvc.begin());
                  rfc_connopt.sysnr = m_RfcConnopt->sysnr;

                  rfc_option.connopt = &rfc_connopt; //<--------

                  You could skip copying the char strings into the C++ strings here. I just did that to avoid having to remember to call Marshal::FreeHGlobal() later on. The important thing is that .Net's wchar_t strings need to be converted to unmanaged char strings, and that rfc_option.connopt needs to point to an unmanaged array.

                  L 1 Reply Last reply
                  0
                  • J Jeff J

                    One way to do this would be to keep an unmanaged struct around for passing to RfcOpen() calls. I assume you will get your string data as CLR String types, so you might want to keep them around in a .Net/GC struct for convenience, as done here (see m_RfcConnopt). When m_RfcConnopt has been filled, its data can be copied into unmanaged data. In this example the CLR Strings are converted to char strings, and then copied into C++ strings for long-term keeping (optional).

                    using namespace System::Runtime::InteropServices;

                    //a GC struct to hold .Net version of the data, just for convenience here
                    __gc struct RFC_ConOpt
                    {
                    String* sHostName;
                    Int32 sysnr;
                    String* sGatewayHost;
                    String* sGatewayService;
                    };

                    RFC_ConOpt *m_RfcConnopt; //the managed class that holds the connopt stuff
                    std::string sHostName, sGatewayHost, sGatewaySvc; //can be kept in class for storage

                    //Before you call RfcOpen()...

                    IntPtr ptr = Marshal::StringToHGlobalAnsi(m_RfcConnopt->sHostName);
                    sHostName = (char*)ptr.ToPointer(); //store in C++ string (optional)
                    Marshal::FreeHGlobal(ptr); //free temp char string

                    ptr = Marshal::StringToHGlobalAnsi(m_RfcConnopt->sGatewayHost);
                    sGatewayHost = (char*)ptr.ToPointer();
                    Marshal::FreeHGlobal(ptr);

                    ptr = Marshal::StringToHGlobalAnsi(m_RfcConnopt->sGatewayService);
                    sGatewaySvc = (char*)ptr.ToPointer();
                    Marshal::FreeHGlobal(ptr);

                    //get pointers to internal char arrays...
                    rfc_connopt.hostname = &(*sHostName.begin());
                    rfc_connopt.gateway_host = &(*sGatewayHost.begin());
                    rfc_connopt.gateway_service = &(*sGatewaySvc.begin());
                    rfc_connopt.sysnr = m_RfcConnopt->sysnr;

                    rfc_option.connopt = &rfc_connopt; //<--------

                    You could skip copying the char strings into the C++ strings here. I just did that to avoid having to remember to call Marshal::FreeHGlobal() later on. The important thing is that .Net's wchar_t strings need to be converted to unmanaged char strings, and that rfc_option.connopt needs to point to an unmanaged array.

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #9

                    That's very nice approach. But I can't change the structure because that function in a DLL. I can interfere to interface of the library. Ahmet Orkun GEDiK

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups