SAFEARRAY as event argument 
Author Message
 SAFEARRAY as event argument

[WinNT 4.0 SP 6.0a + VC6 SP5 + ATL]

Hello,

is it possible to use SAFEARRAY:s as Event (Connection point) argument (I dont want to
pack it in to VARIANT), like this:

    HRESULT TestNotification( [in] SAFEARRAY(BYTE)* myArray );

VB Client code:

    Private Sub TestNotification(myArray() As Byte)
        ' . . .
    Exit Sub

Currently i send the event like this:

    void TestFunc( MyArray myArray )
    {
        BYTE HUGEP* phuge;
        SAFEARRAYBOUND sab[ 1 ];
        sab[ 0 ].lLbound = 0;
        sab[ 0 ].cElements = MYARRAY_SIZE;

        SAFEARRAY* psa = SafeArrayCreate( VT_UI1, 1, sab );

        SafeArrayAccessData( psa, (void HUGEP**)&phuge );
        memcpy( phuge, myArray, sizeof( MyArray ) );
        SafeArrayUnaccessData( psa );

        // Send event
        Fire_TestNotification( psa );

        SafeArrayDestroy( psa );
    }

Connection point looks like this:

    HRESULT Fire_TestNotification( SAFEARRAY *myArray )
    {
        CComVariant varResult;
        T* pT = static_cast<T*>( this );
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[ 1 ];
        int nConnections = m_vec.GetSize();

        for( nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++ ) {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt( nConnectionIndex );
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>( sp.p );

            if( pDispatch != NULL ) {
                VariantClear( &varResult );

                pvars[ 0 ].vt = VT_ARRAY | VT_UI1;
                pvars[ 0 ].parray = myArray;

                DISPPARAMS disp = { pvars, NULL, 1, 0 };
                pDispatch->Invoke( 0x3, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&disp, &varResult, NULL, NULL );
            }
        }

        delete[] pvars;
        return varResult.scode;
    }

When I use this code, my Server will crash after I have sended up to n event. Sometimes it
will crash after 3 and sometimes after 1000 event. Should I free the SAFEARRAY? Am I
freeing it too early/too late?

Thx.

Kimmo Laine



Sat, 07 May 2005 21:05:42 GMT  
 SAFEARRAY as event argument
You'd be freeing it too early if you use the myArray() parameter (or a
reference to it) in your (VB) event handler beyond the scope of the
function.

{L}


Quote:
> [WinNT 4.0 SP 6.0a + VC6 SP5 + ATL]

> Hello,

> is it possible to use SAFEARRAY:s as Event (Connection point) argument (I
dont want to
> pack it in to VARIANT), like this:

>     HRESULT TestNotification( [in] SAFEARRAY(BYTE)* myArray );

> VB Client code:

>     Private Sub TestNotification(myArray() As Byte)
>         ' . . .
>     Exit Sub

> Currently i send the event like this:

>     void TestFunc( MyArray myArray )
>     {
>         BYTE HUGEP* phuge;
>         SAFEARRAYBOUND sab[ 1 ];
>         sab[ 0 ].lLbound = 0;
>         sab[ 0 ].cElements = MYARRAY_SIZE;

>         SAFEARRAY* psa = SafeArrayCreate( VT_UI1, 1, sab );

>         SafeArrayAccessData( psa, (void HUGEP**)&phuge );
>         memcpy( phuge, myArray, sizeof( MyArray ) );
>         SafeArrayUnaccessData( psa );

>         // Send event
>         Fire_TestNotification( psa );

>         SafeArrayDestroy( psa );
>     }

> Connection point looks like this:

>     HRESULT Fire_TestNotification( SAFEARRAY *myArray )
>     {
>         CComVariant varResult;
>         T* pT = static_cast<T*>( this );
>         int nConnectionIndex;
>         CComVariant* pvars = new CComVariant[ 1 ];
>         int nConnections = m_vec.GetSize();

>         for( nConnectionIndex = 0; nConnectionIndex < nConnections;

nConnectionIndex++ ) {

- Show quoted text -

Quote:
>             pT->Lock();
>             CComPtr<IUnknown> sp = m_vec.GetAt( nConnectionIndex );
>             pT->Unlock();
>             IDispatch* pDispatch = reinterpret_cast<IDispatch*>( sp.p );

>             if( pDispatch != NULL ) {
>                 VariantClear( &varResult );

>                 pvars[ 0 ].vt = VT_ARRAY | VT_UI1;
>                 pvars[ 0 ].parray = myArray;

>                 DISPPARAMS disp = { pvars, NULL, 1, 0 };
>                 pDispatch->Invoke( 0x3, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
> &disp, &varResult, NULL, NULL );
>             }
>         }

>         delete[] pvars;
>         return varResult.scode;
>     }

> When I use this code, my Server will crash after I have sended up to n
event. Sometimes it
> will crash after 3 and sometimes after 1000 event. Should I free the
SAFEARRAY? Am I
> freeing it too early/too late?

> Thx.

> Kimmo Laine



Sat, 07 May 2005 21:51:43 GMT  
 SAFEARRAY as event argument
The problem is in this sequence:

pvars[ 0 ].vt = VT_ARRAY | VT_UI1;
pvars[ 0 ].parray = myArray;
delete[] pvars;

You are packing safearray pointer into a variant, thus giving it
ownership. When CComVariant object is destroyed at the end, it calls
VariantClear and destroys the safearray. Then TestFunc destroys it again
and corrupts the heap. Just call pvars[0].Detach() before deleting
pvars.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken


Quote:
> [WinNT 4.0 SP 6.0a + VC6 SP5 + ATL]

> Hello,

> is it possible to use SAFEARRAY:s as Event (Connection point) argument
(I dont want to
> pack it in to VARIANT), like this:

>     HRESULT TestNotification( [in] SAFEARRAY(BYTE)* myArray );

> VB Client code:

>     Private Sub TestNotification(myArray() As Byte)
>         ' . . .
>     Exit Sub

> Currently i send the event like this:

>     void TestFunc( MyArray myArray )
>     {
>         BYTE HUGEP* phuge;
>         SAFEARRAYBOUND sab[ 1 ];
>         sab[ 0 ].lLbound = 0;
>         sab[ 0 ].cElements = MYARRAY_SIZE;

>         SAFEARRAY* psa = SafeArrayCreate( VT_UI1, 1, sab );

>         SafeArrayAccessData( psa, (void HUGEP**)&phuge );
>         memcpy( phuge, myArray, sizeof( MyArray ) );
>         SafeArrayUnaccessData( psa );

>         // Send event
>         Fire_TestNotification( psa );

>         SafeArrayDestroy( psa );
>     }

> Connection point looks like this:

>     HRESULT Fire_TestNotification( SAFEARRAY *myArray )
>     {
>         CComVariant varResult;
>         T* pT = static_cast<T*>( this );
>         int nConnectionIndex;
>         CComVariant* pvars = new CComVariant[ 1 ];
>         int nConnections = m_vec.GetSize();

>         for( nConnectionIndex = 0; nConnectionIndex < nConnections;

nConnectionIndex++ ) {

- Show quoted text -

Quote:
>             pT->Lock();
>             CComPtr<IUnknown> sp = m_vec.GetAt( nConnectionIndex );
>             pT->Unlock();
>             IDispatch* pDispatch = reinterpret_cast<IDispatch*>(
sp.p );

>             if( pDispatch != NULL ) {
>                 VariantClear( &varResult );

>                 pvars[ 0 ].vt = VT_ARRAY | VT_UI1;
>                 pvars[ 0 ].parray = myArray;

>                 DISPPARAMS disp = { pvars, NULL, 1, 0 };
>                 pDispatch->Invoke( 0x3, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
> &disp, &varResult, NULL, NULL );
>             }
>         }

>         delete[] pvars;
>         return varResult.scode;
>     }

> When I use this code, my Server will crash after I have sended up to n
event. Sometimes it
> will crash after 3 and sometimes after 1000 event. Should I free the
SAFEARRAY? Am I
> freeing it too early/too late?

> Thx.

> Kimmo Laine



Sat, 07 May 2005 23:57:54 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. SAFEARRAY Argument Problems

2. Need help with a MFC client with SAFEARRAY argument

3. MFC client access a VB COM Server with SAFEARRAY argument

4. Need help with a MFC client with SAFEARRAY argument

5. MFC client access a VB COM Server with SAFEARRAY argument

6. Problem firing an event from ATL to VB which passes a SAFEARRAY

7. Safearray as Variant parameter to an Event

8. Passing a Safearray in an event

9. SAFEARRAY in event

10. Method vs Event and Safearray's

11. Copy 1D safeArray to 2D safearray

12. How to create safearray or safearray?

 

 
Powered by phpBB® Forum Software