Click here to Skip to main content
15,923,222 members
Home / Discussions / ATL / WTL / STL
   

ATL / WTL / STL

 
GeneralRe: Need to transfer a callback function pointer? Pin
Jörgen Sigvardsson27-Jan-04 21:05
Jörgen Sigvardsson27-Jan-04 21:05 
GeneralRe: Need to transfer a callback function pointer? Pin
freehawk27-Jan-04 23:40
freehawk27-Jan-04 23:40 
GeneralAllocate byte array in ATL server Pin
Chris Losinger26-Jan-04 11:40
professionalChris Losinger26-Jan-04 11:40 
GeneralRe: Allocate byte array in ATL server Pin
Jörgen Sigvardsson26-Jan-04 13:03
Jörgen Sigvardsson26-Jan-04 13:03 
GeneralRe: Allocate byte array in ATL server Pin
Chris Losinger26-Jan-04 13:18
professionalChris Losinger26-Jan-04 13:18 
GeneralRe: Allocate byte array in ATL server Pin
Jörgen Sigvardsson26-Jan-04 13:06
Jörgen Sigvardsson26-Jan-04 13:06 
GeneralRe: Allocate byte array in ATL server Pin
Chris Losinger26-Jan-04 13:19
professionalChris Losinger26-Jan-04 13:19 
GeneralRe: Allocate byte array in ATL server Pin
Lim Bio Liong27-Jan-04 6:08
Lim Bio Liong27-Jan-04 6:08 
Hello Chris,

Don't give up yet, Chris Smile | :) .

>> ... i've always used COleDispatchDriver

Looks like your COM Server is meant to be IDispatch-based or dual interfaced. I did some experiments based on your sample code and came up with the following :

interface IMFIObject : IDispatch
{
[id(1), helpstring("method MFIGetFrame")] HRESULT MFIGetFrame([in] long FrameIdx, [out] VARIANT *pFrameArray, [out,retval] long* Retval);
};

In essence, I changed your second parameter from :

[out] unsigned char **FrameArray

and

[out] SAFEARRAY(unsigned char)*FrameArray

to :

[out] VARIANT *pFrameArray

This is how I implemented the method :

STDMETHODIMP CMFIObject::MFIGetFrame(long FrameIdx, VARIANT *pFrameArray, long *Retval)
{
// TODO: Add your implementation code here
LPBYTE lpbyToReturn = NULL;
SAFEARRAY* lpSafeArrayOfBytes = NULL;

lpbyToReturn = (LPBYTE)malloc(1024);

memset (lpbyToReturn, 'B', 1024);

// Wrap up lpbyToReturn in a SAFEARRAY.
CreateSafeArrayFromBytes
(
(LPBYTE)lpbyToReturn,
(ULONG)1024,
(SAFEARRAY**)&lpSafeArrayOfBytes
);

if (lpSafeArrayOfBytes)
{
// Note well that this function should always return a
// pointer to what is logically returned.
V_VT(pFrameArray) = VT_ARRAY | VT_UI1;
V_ARRAY(pFrameArray) = lpSafeArrayOfBytes;
}

if (lpbyToReturn)
{
free (lpbyToReturn);
lpbyToReturn = NULL;
}

*Retval = 1024;

return S_OK;
}

Here is a summary of what happens in the function :

1. I allocate an array of 1024 bytes and point to it via "lpbyToReturn". The number 1024 is not important. I simply wanted to "allocate and fill a large block of bytes in an ATL object" which is also what you wanted to achieve.

2. I then set all bytes in the array to the letter 'B'. This is done for verification purposes only.

3. I then create a SAFEARRAY and copy the data from the "lpbyToReturn" array to the SAFEARRAY.

4. I then take the second parameter "pFrameArray", which is a pointer to a VARIANT, and make it a valid VARIANT which holds a SAFEARRAY of BYTEs and make the VARIANT point to the newly created SAFEARRAY.

5. Note that I will now need to free the memory of the original array "lpbyToReturn". This is because the SAFEARRAY already contains the same BYTE values in "lpbyToReturn" .

6. Note that I do not free the SAFEARRAY because this is the memory block that is passed back to the client and the client is free to delete it whenever it wants to.

By the way, Chris, I've also supplied the source codes to CreateSafeArrayFromBytes() :

long CMFIObject::CreateSafeArrayFromBytes
(
LPBYTE lpbyBytes,
ULONG ulSize,
SAFEARRAY** ppSafeArrayReceiver
)
{
HRESULT hrRetTemp = S_OK;
SAFEARRAY* pSAFEARRAYRet = NULL;
SAFEARRAYBOUND rgsabound[1];
ULONG ulIndex = 0;
long lRet = 0;

// Initialise receiver.
if (ppSafeArrayReceiver)
{
*ppSafeArrayReceiver = NULL;
}

if (lpbyBytes)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = ulSize;

pSAFEARRAYRet = (SAFEARRAY*)SafeArrayCreate
(
(VARTYPE)VT_UI1,
(unsigned int)1,
(SAFEARRAYBOUND*)rgsabound
);
}

for (ulIndex = 0; ulIndex < ulSize; ulIndex++)
{
long lIndexVector[1];

lIndexVector[0] = ulIndex;

SafeArrayPutElement
(
(SAFEARRAY*)pSAFEARRAYRet,
(long*)lIndexVector,
(void*)(&(lpbyBytes[ulIndex]))
);
}

if (pSAFEARRAYRet)
{
*ppSafeArrayReceiver = pSAFEARRAYRet;
}

return lRet;
}

Now, over to client code. I made sure that my client code will also use the COleDispatchDriver class :

void CVCTestDlg::OnBnClickedButtonGetdynamicarrayfromobject()
{
// TODO: Add your control notification handler code here
IDispatch* pIDispatch = NULL;
COleDispatchDriver ole_disp_driver;
SAFEARRAY* pSafeArrayOfBytes = NULL;

m_spIMFIObject -> QueryInterface (IID_IDispatch, (void**)&pIDispatch);

if (pIDispatch)
{
long lRet = 0;
long lRet2 = 0;
BYTE byParamInfo[2 * 2 + 1];
VARIANTARG pVar;

VariantInit(&pVar);
VariantClear(&pVar);

ole_disp_driver.AttachDispatch(pIDispatch, FALSE);
sprintf ((LPTSTR)byParamInfo, TEXT("%s%s"), VTS_I4, VTS_PVARIANT);
ole_disp_driver.InvokeHelper(0x01, DISPATCH_METHOD, VT_I4, (void*)&lRet, byParamInfo, 1, &pVar);
pIDispatch -> Release();
pIDispatch = NULL;

pSafeArrayOfBytes = pVar.parray;
}

if (pSafeArrayOfBytes)
{
SafeArrayDestroy (pSafeArrayOfBytes);
pSafeArrayOfBytes = NULL;
}

return;
}

Notice that I defined a pointer to a SAFEARRAY object "pSafeArrayOfBytes" which will be filled by the MFIGetFrame() method which is of ordinal 0x01 in my example.

At the end of the function, I will actually delete the SAFEARRAY :

if (pSafeArrayOfBytes)
{
SafeArrayDestroy (pSafeArrayOfBytes);
pSafeArrayOfBytes = NULL;
}




I hope that the above code will be useful to you. Email me if you should want the full scource codes to the above sample. My email address is :

bllim@singnet.com.sg



Best Regards,
Bio.

GeneralRe: Allocate byte array in ATL server Pin
Chris Losinger27-Jan-04 8:59
professionalChris Losinger27-Jan-04 8:59 
GeneralRe: Allocate byte array in ATL server Pin
Lim Bio Liong27-Jan-04 15:47
Lim Bio Liong27-Jan-04 15:47 
GeneralProblem compiling ATL minDependency Visual .NET 2003 Pin
Wim Jans26-Jan-04 10:36
Wim Jans26-Jan-04 10:36 
GeneralWTL Helper class: Message Map unused Pin
peterchen26-Jan-04 9:00
peterchen26-Jan-04 9:00 
GeneralRe: WTL Helper class: Message Map unused Pin
Jörgen Sigvardsson26-Jan-04 9:26
Jörgen Sigvardsson26-Jan-04 9:26 
GeneralRe: WTL Helper class: Message Map unused Pin
peterchen26-Jan-04 9:44
peterchen26-Jan-04 9:44 
GeneralRe: WTL Helper class: Message Map unused Pin
Jörgen Sigvardsson26-Jan-04 9:52
Jörgen Sigvardsson26-Jan-04 9:52 
GeneralIPersistPropertyBag/IPersistPropertyBagImpl question Pin
Vermithrax25-Jan-04 20:37
Vermithrax25-Jan-04 20:37 
GeneralRe: IPersistPropertyBag/IPersistPropertyBagImpl question Pin
Jason De Arte27-Jan-04 6:40
Jason De Arte27-Jan-04 6:40 
GeneralRe: IPersistPropertyBag/IPersistPropertyBagImpl question Pin
Vermithrax27-Jan-04 6:42
Vermithrax27-Jan-04 6:42 
GeneralRe: IPersistPropertyBag/IPersistPropertyBagImpl question Pin
Vermithrax27-Jan-04 10:29
Vermithrax27-Jan-04 10:29 
GeneralRe: IPersistPropertyBag/IPersistPropertyBagImpl question Pin
Jason De Arte27-Jan-04 11:36
Jason De Arte27-Jan-04 11:36 
GeneralRe: IPersistPropertyBag/IPersistPropertyBagImpl question Pin
Vermithrax27-Jan-04 11:37
Vermithrax27-Jan-04 11:37 
GeneralATL Component &gt; .NET issue Pin
dabossuk24-Jan-04 6:20
dabossuk24-Jan-04 6:20 
QuestionHow to call a ATL component from vbscript Pin
Inam23-Jan-04 22:45
Inam23-Jan-04 22:45 
AnswerRe: How to call a ATL component from vbscript Pin
Jörgen Sigvardsson24-Jan-04 9:51
Jörgen Sigvardsson24-Jan-04 9:51 
GeneralSigning ActiveX Controls Pin
Monty221-Jan-04 0:17
Monty221-Jan-04 0:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.