Can a ConnectionPoint Object have function like "HRESULT Test([in, out] Byte* pData)"
-
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
-
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:
Don't treat the BSTR as a null-terminated string! Use
SysAllocStringByteLen
to allocate the space. Cast the BSTR to BYTE* and useSysStringByteLen
to get the byte count. Free the string as normal withSysFreeString
. MSDN does say that aSAFEARRAY
with element typeVT_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' -
Don't treat the BSTR as a null-terminated string! Use
SysAllocStringByteLen
to allocate the space. Cast the BSTR to BYTE* and useSysStringByteLen
to get the byte count. Free the string as normal withSysFreeString
. MSDN does say that aSAFEARRAY
with element typeVT_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'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:
-
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:
The problem is
CComVariant
- that usesSysAllocString
to copy the BSTR. The signature ofSysAllocString
isBSTR SysAllocString(const OLECHAR * sz);
- it assumes that the input BSTR is null-terminated. If you create yourVARIANT
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'
-
The problem is
CComVariant
- that usesSysAllocString
to copy the BSTR. The signature ofSysAllocString
isBSTR SysAllocString(const OLECHAR * sz);
- it assumes that the input BSTR is null-terminated. If you create yourVARIANT
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'
-
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'
-
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'
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:
-
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:
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, anddata
containing the 10 bytes set in theTrigger
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' -
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, anddata
containing the 10 bytes set in theTrigger
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' -
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:
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'