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. COM
  4. Attach Method with SmartPointers causes problems marshaling UDTs?

Attach Method with SmartPointers causes problems marshaling UDTs?

Scheduled Pinned Locked Moved COM
helpcomsysadminsalesbeta-testing
11 Posts 3 Posters 0 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.
  • M Offline
    M Offline
    morenz
    wrote on last edited by
    #1

    Hi everybody, last (I hope) problem. After I released a beta of my preoject, 4 months ago, the customer asked me to change my COM-calling style. I used Smart Pointers with CreateInstance, and server registration on both sides. The customer does not want the server to be registered on client machine, so I was suggested to still use Smart Pointers, but now with CoCreateInstanceEx and Attach. Briefly, it was: ISwitchBoardPtr pISB; ... pISB.CreateInstance(__uuidof(SwitchBoard)); ... ...my code... ... pISB.Release now, it seems it has to be: ISwitchBoardPtr pISB; COSERVERINFO csi = {0, L"10.0.1.9", NULL, 0}; MULTI_QI qi = {&__uuidof(ISwitchBoard), NULL, S_OK}; HRESULT hr = CoCreateInstanceEx(__uuidof(SwitchBoard), NULL, CLSCTX_REMOTE_SERVER, &csi, 1, &qi); //error checking omitted ISwitchBoard *_pISB = static_cast(qi.pItf); pSB.Attach(_pISB); In this object I expose several UDTs, even big and complex (imagine a structure that has as one of its fields a SafeArray containing another structure), and when I used the first method, everything worked fine and the customer was happy, but when I started to use the second method, NONE of my UDTs is marshaled anymore. I get crashes in client (while the server keeps running fine, logically) when I try to get as [out] or [out, retval] parameters one of my UDTs. I'm stuck. The only thing I thought about is that qi.pItf is a IUnknown * type, while my objects expose IDispatch interfaces, but IDispatch is derived from IUnknown, as every interface in COM, so it should work, shouldn't it? Thanks for your kind help again...:)

    M R 2 Replies Last reply
    0
    • M morenz

      Hi everybody, last (I hope) problem. After I released a beta of my preoject, 4 months ago, the customer asked me to change my COM-calling style. I used Smart Pointers with CreateInstance, and server registration on both sides. The customer does not want the server to be registered on client machine, so I was suggested to still use Smart Pointers, but now with CoCreateInstanceEx and Attach. Briefly, it was: ISwitchBoardPtr pISB; ... pISB.CreateInstance(__uuidof(SwitchBoard)); ... ...my code... ... pISB.Release now, it seems it has to be: ISwitchBoardPtr pISB; COSERVERINFO csi = {0, L"10.0.1.9", NULL, 0}; MULTI_QI qi = {&__uuidof(ISwitchBoard), NULL, S_OK}; HRESULT hr = CoCreateInstanceEx(__uuidof(SwitchBoard), NULL, CLSCTX_REMOTE_SERVER, &csi, 1, &qi); //error checking omitted ISwitchBoard *_pISB = static_cast(qi.pItf); pSB.Attach(_pISB); In this object I expose several UDTs, even big and complex (imagine a structure that has as one of its fields a SafeArray containing another structure), and when I used the first method, everything worked fine and the customer was happy, but when I started to use the second method, NONE of my UDTs is marshaled anymore. I get crashes in client (while the server keeps running fine, logically) when I try to get as [out] or [out, retval] parameters one of my UDTs. I'm stuck. The only thing I thought about is that qi.pItf is a IUnknown * type, while my objects expose IDispatch interfaces, but IDispatch is derived from IUnknown, as every interface in COM, so it should work, shouldn't it? Thanks for your kind help again...:)

      M Offline
      M Offline
      Milton Karimbekallil
      wrote on last edited by
      #2

      How you are populating the UDTs? as safearray? If not universal marshaler cant marshal them as UDTS are unnown type for them. Also register thr type library on the client if you didnt do so. rgds..mil10.

      1 Reply Last reply
      0
      • M morenz

        Hi everybody, last (I hope) problem. After I released a beta of my preoject, 4 months ago, the customer asked me to change my COM-calling style. I used Smart Pointers with CreateInstance, and server registration on both sides. The customer does not want the server to be registered on client machine, so I was suggested to still use Smart Pointers, but now with CoCreateInstanceEx and Attach. Briefly, it was: ISwitchBoardPtr pISB; ... pISB.CreateInstance(__uuidof(SwitchBoard)); ... ...my code... ... pISB.Release now, it seems it has to be: ISwitchBoardPtr pISB; COSERVERINFO csi = {0, L"10.0.1.9", NULL, 0}; MULTI_QI qi = {&__uuidof(ISwitchBoard), NULL, S_OK}; HRESULT hr = CoCreateInstanceEx(__uuidof(SwitchBoard), NULL, CLSCTX_REMOTE_SERVER, &csi, 1, &qi); //error checking omitted ISwitchBoard *_pISB = static_cast(qi.pItf); pSB.Attach(_pISB); In this object I expose several UDTs, even big and complex (imagine a structure that has as one of its fields a SafeArray containing another structure), and when I used the first method, everything worked fine and the customer was happy, but when I started to use the second method, NONE of my UDTs is marshaled anymore. I get crashes in client (while the server keeps running fine, logically) when I try to get as [out] or [out, retval] parameters one of my UDTs. I'm stuck. The only thing I thought about is that qi.pItf is a IUnknown * type, while my objects expose IDispatch interfaces, but IDispatch is derived from IUnknown, as every interface in COM, so it should work, shouldn't it? Thanks for your kind help again...:)

        R Offline
        R Offline
        Roger Stoltz
        wrote on last edited by
        #3

        How can the use of smart pointers cause problems with marshalling? The call is made exactly the same way to the server and the type library is still the same. Am I missing something here? Since you're mentioning IDispatch I guess that the interface in question is declared in the IDL-file as either dispinterface or has the oleautomation attribute set. If this is the case, then Mil10's comments applies: you cannot pass UDTs through an automation interface unless you convert them into SafeArrays of e.g. char. The universal marshaller can only handle types that can be represented with a VARIANT. If you are indeed using a custom interface that doesn't derive from IDispatch you have to deal with the marshalling by yourself and also distribute and register the marshalling dll that contains the proxy/stub. As I understood your execution environment, the server is located on another machine than the client. This means that the proxy/stub has to be registered on both machines, otherwise at least the marshalling won't work. Hope this helps -- Roger


        It's suppose to be hard, otherwise anybody could do it!

        M 1 Reply Last reply
        0
        • R Roger Stoltz

          How can the use of smart pointers cause problems with marshalling? The call is made exactly the same way to the server and the type library is still the same. Am I missing something here? Since you're mentioning IDispatch I guess that the interface in question is declared in the IDL-file as either dispinterface or has the oleautomation attribute set. If this is the case, then Mil10's comments applies: you cannot pass UDTs through an automation interface unless you convert them into SafeArrays of e.g. char. The universal marshaller can only handle types that can be represented with a VARIANT. If you are indeed using a custom interface that doesn't derive from IDispatch you have to deal with the marshalling by yourself and also distribute and register the marshalling dll that contains the proxy/stub. As I understood your execution environment, the server is located on another machine than the client. This means that the proxy/stub has to be registered on both machines, otherwise at least the marshalling won't work. Hope this helps -- Roger


          It's suppose to be hard, otherwise anybody could do it!

          M Offline
          M Offline
          Milton Karimbekallil
          wrote on last edited by
          #4

          Exactly, either use universal marshler compatiable types, ie Safearrays with variants and register the universal marshler's proxy, ie the type library file on the cleint. Or Go for custom marshaling and register the custom proxy stub dll on the cleint. I dont think this second option is feasible. It will be better to go for the first option of universl marshaling. rgds...mil10

          M 1 Reply Last reply
          0
          • M Milton Karimbekallil

            Exactly, either use universal marshler compatiable types, ie Safearrays with variants and register the universal marshler's proxy, ie the type library file on the cleint. Or Go for custom marshaling and register the custom proxy stub dll on the cleint. I dont think this second option is feasible. It will be better to go for the first option of universl marshaling. rgds...mil10

            M Offline
            M Offline
            morenz
            wrote on last edited by
            #5

            This is one of the UDTs I pass (both structures have been declared, in IDL file, with an UUID, I use SAFEARRAY with VT_RECORD and GetRecordInfoFromGuids on both server and client side): struct RGBValue_struct { unsigned int R, unsigned int G, unsigned int B, unsigned int alpha; }RGBValue; struct COM_IVA_Image_struct { SAFEARRAY(RGBValue) saPoints, int rows, int cols; }COM_IVA_IMAGE; the method declaration, in server side, is HRESULT loadImage([in] BSTR fileName, [out, retval] COM_IVA_Image IVAImage); and the call, on client side, is COM_IVA_Image IVAImage; IVisionEnginePtr pIVE; // that is my interface IVA_Image = pIVE->loadImage("2230.tif"); where am I wrong? thanx again Morenz

            R 1 Reply Last reply
            0
            • M morenz

              This is one of the UDTs I pass (both structures have been declared, in IDL file, with an UUID, I use SAFEARRAY with VT_RECORD and GetRecordInfoFromGuids on both server and client side): struct RGBValue_struct { unsigned int R, unsigned int G, unsigned int B, unsigned int alpha; }RGBValue; struct COM_IVA_Image_struct { SAFEARRAY(RGBValue) saPoints, int rows, int cols; }COM_IVA_IMAGE; the method declaration, in server side, is HRESULT loadImage([in] BSTR fileName, [out, retval] COM_IVA_Image IVAImage); and the call, on client side, is COM_IVA_Image IVAImage; IVisionEnginePtr pIVE; // that is my interface IVA_Image = pIVE->loadImage("2230.tif"); where am I wrong? thanx again Morenz

              R Offline
              R Offline
              Roger Stoltz
              wrote on last edited by
              #6

              morenz wrote:

              where am I wrong?

              Hard to say since you haven't told us whether you're using an automation interface or not and what kind of marshalling you're using. IF you're using the universal marshaller then the COM_IVA_IMAGE structure is unsupported since it's not an automation data type that can be represented with a VARIANT. Even if the members of the COM_IVA_IMAGE structure are oleautomation compatible, the structure is not. Consider altering the parameter list for the loadImage() function to HRESULT loadImage( [in] BSTR fileName, [out] long* rows, [out] long* cols, [out, retval] SAFEARRAY(char)* saPoints ); -- Roger


              It's suppose to be hard, otherwise anybody could do it!

              M 1 Reply Last reply
              0
              • R Roger Stoltz

                morenz wrote:

                where am I wrong?

                Hard to say since you haven't told us whether you're using an automation interface or not and what kind of marshalling you're using. IF you're using the universal marshaller then the COM_IVA_IMAGE structure is unsupported since it's not an automation data type that can be represented with a VARIANT. Even if the members of the COM_IVA_IMAGE structure are oleautomation compatible, the structure is not. Consider altering the parameter list for the loadImage() function to HRESULT loadImage( [in] BSTR fileName, [out] long* rows, [out] long* cols, [out, retval] SAFEARRAY(char)* saPoints ); -- Roger


                It's suppose to be hard, otherwise anybody could do it!

                M Offline
                M Offline
                morenz
                wrote on last edited by
                #7

                ok, I understood, you hit the correct point. I'm using dual interfaces (I noticed that using or not the oleautomation keyword does not affect things) and I'm using universal marshaling. One last thing: WHY does it work with CreateInstance? Just because CreateInstance uses the registery-based technique? How can it manage better these UDTs? Thanks again for your (your and Mil10's) precious help, that was not the first COM I created, but I was never gone so deep in COM architecture... Best regards, Morenz

                R 1 Reply Last reply
                0
                • M morenz

                  ok, I understood, you hit the correct point. I'm using dual interfaces (I noticed that using or not the oleautomation keyword does not affect things) and I'm using universal marshaling. One last thing: WHY does it work with CreateInstance? Just because CreateInstance uses the registery-based technique? How can it manage better these UDTs? Thanks again for your (your and Mil10's) precious help, that was not the first COM I created, but I was never gone so deep in COM architecture... Best regards, Morenz

                  R Offline
                  R Offline
                  Roger Stoltz
                  wrote on last edited by
                  #8

                  morenz wrote:

                  I noticed that using or not the oleautomation keyword does not affect things

                  That's because since it's a dual interface it's implicitly an automation interface.

                  morenz wrote:

                  WHY does it work with CreateInstance?... How can it manage better these UDTs?

                  To put it simple: it cannot. Since it's the same interface and the same marshaller this won't change. I suspect that when you used CreateInstance() you had a server registered on the same machine as the client and it was invoked as an in-process server so there was no need for marshalling, hence it would seem to handle the UDTs better but in fact they were never "handled" at all. But I'm only guessing here. -- Roger


                  It's suppose to be hard, otherwise anybody could do it!

                  M 1 Reply Last reply
                  0
                  • R Roger Stoltz

                    morenz wrote:

                    I noticed that using or not the oleautomation keyword does not affect things

                    That's because since it's a dual interface it's implicitly an automation interface.

                    morenz wrote:

                    WHY does it work with CreateInstance?... How can it manage better these UDTs?

                    To put it simple: it cannot. Since it's the same interface and the same marshaller this won't change. I suspect that when you used CreateInstance() you had a server registered on the same machine as the client and it was invoked as an in-process server so there was no need for marshalling, hence it would seem to handle the UDTs better but in fact they were never "handled" at all. But I'm only guessing here. -- Roger


                    It's suppose to be hard, otherwise anybody could do it!

                    M Offline
                    M Offline
                    morenz
                    wrote on last edited by
                    #9

                    No, I verified several times... The server is registered also in client machine (with /RegServer switch), but it's configured (via DCOMCNFG) to go ONLY remote. To be sure, I referred for my test to some image files there were present only on server machine, and I referred them putting down the entire path when calling server methods. If it was like that you are saying, I should get a "file not found" error, instead it did all that it had to do with no problems at all. Also, if I unplug network cable, I get a "RPC Server Unavailable" error. Last question: if I decide not to use dual interfaces (therefore using IUnknown instead of IDispatch), can I get rid of this problem? If I decide doing custom marshaling where can I get an example of this technique (that I've never seen before?) Thanx again.... Morenz

                    R 1 Reply Last reply
                    0
                    • M morenz

                      No, I verified several times... The server is registered also in client machine (with /RegServer switch), but it's configured (via DCOMCNFG) to go ONLY remote. To be sure, I referred for my test to some image files there were present only on server machine, and I referred them putting down the entire path when calling server methods. If it was like that you are saying, I should get a "file not found" error, instead it did all that it had to do with no problems at all. Also, if I unplug network cable, I get a "RPC Server Unavailable" error. Last question: if I decide not to use dual interfaces (therefore using IUnknown instead of IDispatch), can I get rid of this problem? If I decide doing custom marshaling where can I get an example of this technique (that I've never seen before?) Thanx again.... Morenz

                      R Offline
                      R Offline
                      Roger Stoltz
                      wrote on last edited by
                      #10

                      Sorry Morenz, I haven't done custom marshalling so I cannot guide you in the howto process of custom marshalling. However, I do know that with custom marshalling you can marshal any UDT you like since you have control of how it's done and transferred through the RPC channel. I suspect that the howto-part is non-trivial and perhaps that might make you consider still using universal marshalling and automation interfaces. If you're going for custom marshalling I guess you have to buy a good book about the subject...:sigh: -- Roger


                      It's suppose to be hard, otherwise anybody could do it!

                      M 1 Reply Last reply
                      0
                      • R Roger Stoltz

                        Sorry Morenz, I haven't done custom marshalling so I cannot guide you in the howto process of custom marshalling. However, I do know that with custom marshalling you can marshal any UDT you like since you have control of how it's done and transferred through the RPC channel. I suspect that the howto-part is non-trivial and perhaps that might make you consider still using universal marshalling and automation interfaces. If you're going for custom marshalling I guess you have to buy a good book about the subject...:sigh: -- Roger


                        It's suppose to be hard, otherwise anybody could do it!

                        M Offline
                        M Offline
                        morenz
                        wrote on last edited by
                        #11

                        ok, no matter. The final decision will be taken by the customer, and it will be based on how SOON they want the project :laugh: In the worst case (custom marshaling) I think I will buy a book and, why not, consider to give a shot in some serious forum, like this...:-D Thanks for all. Enjoy Morenz P.S. Pardon me, but in your footnote (or signature) you have a typo: you should have "It's supposed to be hard" instead of "It's suppose to be hard":laugh:

                        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