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.
  • S samfromcn

    :wtf:I want to transfer a large data buffer, maybe 10k. Who can tell me how to realize my idea?

    M Offline
    M Offline
    Michael Dunn
    wrote on last edited by
    #2

    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 1 Reply Last reply
    0
    • 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