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. ATL / WTL / STL
  4. Can a ConnectionPoint Object have function like "HRESULT Test([in, out] Byte* pData)"

Can a ConnectionPoint Object have function like "HRESULT Test([in, out] Byte* pData)"

Scheduled Pinned Locked Moved ATL / WTL / STL
tutorialquestion
12 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 Michael Dunn

    There is already an automation-compatible type for transferring a block of bytes: BSTR. --Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | 1ClickPicGrabber | CP SearchBar v2.0.2 | C++ Forum FAQ Strange things are afoot at the U+004B U+20DD

    S Offline
    S Offline
    samfromcn
    wrote on last edited by
    #3

    thanks a lot, please tell me , if I have a data buffer like "BYTE* p = myData;// there are many 0 values in buffer", I know buffer 's length, how to transfer the data use BSTR?:confused:

    S 1 Reply Last reply
    0
    • S samfromcn

      thanks a lot, please tell me , if I have a data buffer like "BYTE* p = myData;// there are many 0 values in buffer", I know buffer 's length, how to transfer the data use BSTR?:confused:

      S Offline
      S Offline
      Stuart Dootson
      wrote on last edited by
      #4

      Don't treat the BSTR as a null-terminated string! Use SysAllocStringByteLen to allocate the space. Cast the BSTR to BYTE* and use SysStringByteLen to get the byte count. Free the string as normal with SysFreeString. MSDN does say that a SAFEARRAY with element type VT_UI1 is preferred, in order that you don't get translations on 16/32-bit borders...but a) who uses 16-bit OLE now?, and b) BSTR is a lot easier in C++ :-D Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

      S 1 Reply Last reply
      0
      • S Stuart Dootson

        Don't treat the BSTR as a null-terminated string! Use SysAllocStringByteLen to allocate the space. Cast the BSTR to BYTE* and use SysStringByteLen to get the byte count. Free the string as normal with SysFreeString. MSDN does say that a SAFEARRAY with element type VT_UI1 is preferred, in order that you don't get translations on 16/32-bit borders...but a) who uses 16-bit OLE now?, and b) BSTR is a lot easier in C++ :-D Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

        S Offline
        S Offline
        samfromcn
        wrote on last edited by
        #5

        It seems as if the method does not work. Following my code : 1:declare interface------ dispinterface _IMyEvents { properties: methods: [id(1), helpstring("method Test")] HRESULT Test([in]DWORD dwLen, [in] BSTR pData); }; 2:method implement------- HRESULT Fire_Test(ULONG dwLen, BSTR pData) { CComVariant varResult; T* pT = static_cast(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast(sp.p); if (pDispatch != NULL) { VariantClear(&varResult); pvars[1] = (int)dwLen; pvars[0] = pData; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL); } } delete[] pvars; return varResult.scode; } 3:call method in Server Object------ { char a[10] = _T("abcdef"); a[8] = 'x'; BSTR bstr = SysAllocStringByteLen(a, 10); Fire_Test(10, bstr); } 4:called in Client ------- long CEventNotifySink::OnTest(DWORD dwLen, BSTR pData) { UINT len = SysStringByteLen (pData); // result: len!=10 BYTE * p = (BYTE*)pData; // pData refs wrong address SysFreeString(pData); return 0; } where is wrong?:confused:

        S 1 Reply Last reply
        0
        • S samfromcn

          It seems as if the method does not work. Following my code : 1:declare interface------ dispinterface _IMyEvents { properties: methods: [id(1), helpstring("method Test")] HRESULT Test([in]DWORD dwLen, [in] BSTR pData); }; 2:method implement------- HRESULT Fire_Test(ULONG dwLen, BSTR pData) { CComVariant varResult; T* pT = static_cast(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast(sp.p); if (pDispatch != NULL) { VariantClear(&varResult); pvars[1] = (int)dwLen; pvars[0] = pData; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL); } } delete[] pvars; return varResult.scode; } 3:call method in Server Object------ { char a[10] = _T("abcdef"); a[8] = 'x'; BSTR bstr = SysAllocStringByteLen(a, 10); Fire_Test(10, bstr); } 4:called in Client ------- long CEventNotifySink::OnTest(DWORD dwLen, BSTR pData) { UINT len = SysStringByteLen (pData); // result: len!=10 BYTE * p = (BYTE*)pData; // pData refs wrong address SysFreeString(pData); return 0; } where is wrong?:confused:

          S Offline
          S Offline
          Stuart Dootson
          wrote on last edited by
          #6

          The problem is CComVariant - that uses SysAllocString to copy the BSTR. The signature of SysAllocString is BSTR SysAllocString(const OLECHAR * sz); - it assumes that the input BSTR is null-terminated. If you create your VARIANT manually, you shouldn't have a problem:

             VARIANT v;
             V_VT(v) = VT_BSTR;
             V_BSTR(v) = pData;
          

          Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

          S 1 Reply Last reply
          0
          • S Stuart Dootson

            The problem is CComVariant - that uses SysAllocString to copy the BSTR. The signature of SysAllocString is BSTR SysAllocString(const OLECHAR * sz); - it assumes that the input BSTR is null-terminated. If you create your VARIANT manually, you shouldn't have a problem:

               VARIANT v;
               V_VT(v) = VT_BSTR;
               V_BSTR(v) = pData;
            

            Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

            S Offline
            S Offline
            samfromcn
            wrote on last edited by
            #7

            not only length, the "pData" refer wrong address, data is wrong.

            S 1 Reply Last reply
            0
            • S samfromcn

              not only length, the "pData" refer wrong address, data is wrong.

              S Offline
              S Offline
              Stuart Dootson
              wrote on last edited by
              #8

              Creating the CComVariant *copied* the BSTR - i.e. created a new one. It will therefore have a different address from the original. Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

              S 1 Reply Last reply
              0
              • S Stuart Dootson

                Creating the CComVariant *copied* the BSTR - i.e. created a new one. It will therefore have a different address from the original. Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                S Offline
                S Offline
                samfromcn
                wrote on last edited by
                #9

                I trace my my code and find that, in ATL, COleDispatchImpl::Invoke(...) method calls CallMemberFunc(...), and CallMemberFunc() method calls PushStackArgs(...), there is such a sentence----"pArgTemp->bstrVal = AfxBSTR2ABSTR(pArg->bstrVal);" in PushStackArgs(...) method, After this call happened, my buffer data lost:sigh:. how to resolve the problem?:omg:

                S 1 Reply Last reply
                0
                • S samfromcn

                  I trace my my code and find that, in ATL, COleDispatchImpl::Invoke(...) method calls CallMemberFunc(...), and CallMemberFunc() method calls PushStackArgs(...), there is such a sentence----"pArgTemp->bstrVal = AfxBSTR2ABSTR(pArg->bstrVal);" in PushStackArgs(...) method, After this call happened, my buffer data lost:sigh:. how to resolve the problem?:omg:

                  S Offline
                  S Offline
                  Stuart Dootson
                  wrote on last edited by
                  #10

                  Hmmmm - COleDispatchImpl is part of MFC, not ATL... Anyway - I've built a sample COM object (with connection point) using ATL and a harness executable (built using ATL to implement the connection point interface). This passes a BSTR as the event parameter and it seems to work fine... I've got this code to fire the event:

                  STDMETHODIMP CPooh::Trigger()
                  {
                     BSTR bs;
                     BYTE a[10] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4 };
                     bs = ::SysAllocStringByteLen((const char*)a, 10);
                  
                     Fire_Pooh(bs);
                     
                     return S_OK;
                  }
                  

                  and this code catching the event:

                  void __stdcall OnPooh(BSTR bs)
                  {
                     size_t s = ::SysStringByteLen(bs);
                     BYTE* data = (BYTE*)bs;
                  }
                  

                  I'm getting s set to 10, and data containing the 10 bytes set in the Trigger method. As I said - I'm using ATL code all the way and it works fine... Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                  S 1 Reply Last reply
                  0
                  • S Stuart Dootson

                    Hmmmm - COleDispatchImpl is part of MFC, not ATL... Anyway - I've built a sample COM object (with connection point) using ATL and a harness executable (built using ATL to implement the connection point interface). This passes a BSTR as the event parameter and it seems to work fine... I've got this code to fire the event:

                    STDMETHODIMP CPooh::Trigger()
                    {
                       BSTR bs;
                       BYTE a[10] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x0, 0x1, 0x2, 0x3, 0x4 };
                       bs = ::SysAllocStringByteLen((const char*)a, 10);
                    
                       Fire_Pooh(bs);
                       
                       return S_OK;
                    }
                    

                    and this code catching the event:

                    void __stdcall OnPooh(BSTR bs)
                    {
                       size_t s = ::SysStringByteLen(bs);
                       BYTE* data = (BYTE*)bs;
                    }
                    

                    I'm getting s set to 10, and data containing the 10 bytes set in the Trigger method. As I said - I'm using ATL code all the way and it works fine... Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                    S Offline
                    S Offline
                    samfromcn
                    wrote on last edited by
                    #11

                    thank you, Stuart Dootson. I wrote client with MFC, there must be something wrong in my code. Later I wrote a new client with ATL, everything works fine.:laugh::rose:

                    S 1 Reply Last reply
                    0
                    • S samfromcn

                      thank you, Stuart Dootson. I wrote client with MFC, there must be something wrong in my code. Later I wrote a new client with ATL, everything works fine.:laugh::rose:

                      S Offline
                      S Offline
                      Stuart Dootson
                      wrote on last edited by
                      #12

                      samfromcn wrote: something wrong in my code I'd bet that it's in the MFC code - that's why I use ATL for COM code ;) Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                      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