moving arrays from un-managed to managed code. 
Author Message
 moving arrays from un-managed to managed code.

I have a legacy real-time multi-threaded app, written in C++.

I eliminated all the MFC and ATL code, so all I had left was the core of the
application which is time critical and mult-threaded.  Around this I added a
managed C++ layer.  The GUI and remotting is being done in C#.

For updating my graphics display, as well as being able to grab a snap shot
of the display data remotely, I need to move arrays from the un-managed to
the managed code once per second.  I need to move 3 arrays of 4096 integers
once a second.

I have come up with the following code, but was wondering if there is a more
efficient way of doing this.

Here is the managed C++ layer:

System::Array* CMHistogram::GrabData()

{

   int size = m_pHistogram->GetSize();

   int* udata = new int[size];

   m_pHistogram->GrabData( udata, size );

   int mdata __gc[] = new int __gc[size];

   for( int j = 0 ; j < size ; j++ )

   {

      mdata[j] = udata[j];

   }

   delete[] udata;

   return( mdata );

Quote:
}

and here is the un-managed layer:

void CHistogram::GrabData( int* pData, int& size )

{

   if( size > m_nBins )

   {

      size = m_nBins;

   }

   EnterCriticalSection( &m_csLock );

   {

      memcpy( pData, m_Data, size * sizeof( int ) );

   }

   LeaveCriticalSection( &m_csLock );

   m_bDirty = false;

Quote:
}

Here is the C# layer, with the timer set for 1 sec:

private int[] m_Buffer;

private CMHistogram m_Hist;

private void timer_Tick(object sender, System.EventArgs e)

{

   if( UpdateData() )

   {

      Display.Invalidate();

      UpdateControlBar();

   }

Quote:
}

private bool UpdateData()

{

   bool bDirty = m_Hist.Dirty;

   if( bDirty )

   {

      m_Buffer = (int[])m_Hist.GrabData();

      CalcStatistics();

   }

   return( bDirty );

Quote:
}

Bill

--

http://www.*-*-*.com/



Wed, 18 Feb 2004 01:39:51 GMT  
 moving arrays from un-managed to managed code.
Hi Bill,

A way to do this which may be faster is to copy the data using native code.

int mdata __gc[] = new int __gc[size];

   for( int j = 0 ; j < size ; j++ )

   {

      mdata[j] = udata[j];

   }

could be re-written as

int mdata __gc[] = new int __gc[size];
int __pin * pmdata = &pmdata[0]; // pin the managed array

memcpy(udata, pmdata, size * sizeof(int));

You need to pin the managed array first to prevent the possibility of the
garbage collector moving it during the call to memcpy.

--
David Wolfram
Visual C++ Compiler Team

This posting is covered by the Conditions of Use:
http://www.microsoft.com/info/cpyright.htm


Quote:
> I have a legacy real-time multi-threaded app, written in C++.

> I eliminated all the MFC and ATL code, so all I had left was the core of
the
> application which is time critical and mult-threaded.  Around this I added
a
> managed C++ layer.  The GUI and remotting is being done in C#.

> For updating my graphics display, as well as being able to grab a snap
shot
> of the display data remotely, I need to move arrays from the un-managed to
> the managed code once per second.  I need to move 3 arrays of 4096
integers
> once a second.

> I have come up with the following code, but was wondering if there is a
more
> efficient way of doing this.

> Here is the managed C++ layer:

> System::Array* CMHistogram::GrabData()

> {

>    int size = m_pHistogram->GetSize();

>    int* udata = new int[size];

>    m_pHistogram->GrabData( udata, size );

>    int mdata __gc[] = new int __gc[size];

>    for( int j = 0 ; j < size ; j++ )

>    {

>       mdata[j] = udata[j];

>    }

>    delete[] udata;

>    return( mdata );

> }

> and here is the un-managed layer:

> void CHistogram::GrabData( int* pData, int& size )

> {

>    if( size > m_nBins )

>    {

>       size = m_nBins;

>    }

>    EnterCriticalSection( &m_csLock );

>    {

>       memcpy( pData, m_Data, size * sizeof( int ) );

>    }

>    LeaveCriticalSection( &m_csLock );

>    m_bDirty = false;

> }

> Here is the C# layer, with the timer set for 1 sec:

> private int[] m_Buffer;

> private CMHistogram m_Hist;

> private void timer_Tick(object sender, System.EventArgs e)

> {

>    if( UpdateData() )

>    {

>       Display.Invalidate();

>       UpdateControlBar();

>    }

> }

> private bool UpdateData()

> {

>    bool bDirty = m_Hist.Dirty;

>    if( bDirty )

>    {

>       m_Buffer = (int[])m_Hist.GrabData();

>       CalcStatistics();

>    }

>    return( bDirty );

> }

> Bill

> --

> http://www.componentsnotebook.com/



Wed, 18 Feb 2004 05:08:32 GMT  
 moving arrays from un-managed to managed code.
The call to memcpy should read

memcpy(pmdata, udata, size * sizeof(int));

for copying the native array. Sorry for the typo.

--
David Wolfram
Visual C++ Compiler Team

This posting is covered by the Conditions of Use:
http://www.microsoft.com/info/cpyright.htm



Quote:
> Hi Bill,

> A way to do this which may be faster is to copy the data using native
code.

> int mdata __gc[] = new int __gc[size];

>    for( int j = 0 ; j < size ; j++ )

>    {

>       mdata[j] = udata[j];

>    }

> could be re-written as

> int mdata __gc[] = new int __gc[size];
> int __pin * pmdata = &pmdata[0]; // pin the managed array

> memcpy(udata, pmdata, size * sizeof(int));

> You need to pin the managed array first to prevent the possibility of the
> garbage collector moving it during the call to memcpy.

> --
> David Wolfram
> Visual C++ Compiler Team

> This posting is covered by the Conditions of Use:
> http://www.microsoft.com/info/cpyright.htm



> > I have a legacy real-time multi-threaded app, written in C++.

> > I eliminated all the MFC and ATL code, so all I had left was the core of
> the
> > application which is time critical and mult-threaded.  Around this I
added
> a
> > managed C++ layer.  The GUI and remotting is being done in C#.

> > For updating my graphics display, as well as being able to grab a snap
> shot
> > of the display data remotely, I need to move arrays from the un-managed
to
> > the managed code once per second.  I need to move 3 arrays of 4096
> integers
> > once a second.

> > I have come up with the following code, but was wondering if there is a
> more
> > efficient way of doing this.

> > Here is the managed C++ layer:

> > System::Array* CMHistogram::GrabData()

> > {

> >    int size = m_pHistogram->GetSize();

> >    int* udata = new int[size];

> >    m_pHistogram->GrabData( udata, size );

> >    int mdata __gc[] = new int __gc[size];

> >    for( int j = 0 ; j < size ; j++ )

> >    {

> >       mdata[j] = udata[j];

> >    }

> >    delete[] udata;

> >    return( mdata );

> > }

> > and here is the un-managed layer:

> > void CHistogram::GrabData( int* pData, int& size )

> > {

> >    if( size > m_nBins )

> >    {

> >       size = m_nBins;

> >    }

> >    EnterCriticalSection( &m_csLock );

> >    {

> >       memcpy( pData, m_Data, size * sizeof( int ) );

> >    }

> >    LeaveCriticalSection( &m_csLock );

> >    m_bDirty = false;

> > }

> > Here is the C# layer, with the timer set for 1 sec:

> > private int[] m_Buffer;

> > private CMHistogram m_Hist;

> > private void timer_Tick(object sender, System.EventArgs e)

> > {

> >    if( UpdateData() )

> >    {

> >       Display.Invalidate();

> >       UpdateControlBar();

> >    }

> > }

> > private bool UpdateData()

> > {

> >    bool bDirty = m_Hist.Dirty;

> >    if( bDirty )

> >    {

> >       m_Buffer = (int[])m_Hist.GrabData();

> >       CalcStatistics();

> >    }

> >    return( bDirty );

> > }

> > Bill

> > --

> > http://www.componentsnotebook.com/



Wed, 18 Feb 2004 05:17:04 GMT  
 moving arrays from un-managed to managed code.
Thanks David for reminding me about __pin.

What I am wondering about is what happens to the pinned array, is it free to
be moved by the garbage collector after the pointer goes out of scope?

My latest code is:

System::Array* CMHistogram::GrabData()

{

   int size = m_pHistogram->GetSize();

   int mdata __gc[] = new int __gc[size];

   int __pin * pmdata = &mdata[0];

   m_pHistogram->GrabData( pmdata, size );

   return( mdata );

Quote:
}

void CHistogram::GrabData( int* pData, int& size )

{

   EnterCriticalSection( &m_csLock );

   {

       memcpy( pData, m_Data, size * sizeof( int ) );

   }

   LeaveCriticalSection( &m_csLock );

Quote:
}

Bill

--

http://www.componentsnotebook.com



Quote:
> The call to memcpy should read

> memcpy(pmdata, udata, size * sizeof(int));

> for copying the native array. Sorry for the typo.

> --
> David Wolfram
> Visual C++ Compiler Team

> This posting is covered by the Conditions of Use:
> http://www.microsoft.com/info/cpyright.htm



> > Hi Bill,

> > A way to do this which may be faster is to copy the data using native
> code.

> > int mdata __gc[] = new int __gc[size];

> >    for( int j = 0 ; j < size ; j++ )

> >    {

> >       mdata[j] = udata[j];

> >    }

> > could be re-written as

> > int mdata __gc[] = new int __gc[size];
> > int __pin * pmdata = &pmdata[0]; // pin the managed array

> > memcpy(udata, pmdata, size * sizeof(int));

> > You need to pin the managed array first to prevent the possibility of
the
> > garbage collector moving it during the call to memcpy.

> > --
> > David Wolfram
> > Visual C++ Compiler Team

> > This posting is covered by the Conditions of Use:
> > http://www.microsoft.com/info/cpyright.htm



> > > I have a legacy real-time multi-threaded app, written in C++.

> > > I eliminated all the MFC and ATL code, so all I had left was the core
of
> > the
> > > application which is time critical and mult-threaded.  Around this I
> added
> > a
> > > managed C++ layer.  The GUI and remotting is being done in C#.

> > > For updating my graphics display, as well as being able to grab a snap
> > shot
> > > of the display data remotely, I need to move arrays from the
un-managed
> to
> > > the managed code once per second.  I need to move 3 arrays of 4096
> > integers
> > > once a second.

> > > I have come up with the following code, but was wondering if there is
a
> > more
> > > efficient way of doing this.

> > > Here is the managed C++ layer:

> > > System::Array* CMHistogram::GrabData()

> > > {

> > >    int size = m_pHistogram->GetSize();

> > >    int* udata = new int[size];

> > >    m_pHistogram->GrabData( udata, size );

> > >    int mdata __gc[] = new int __gc[size];

> > >    for( int j = 0 ; j < size ; j++ )

> > >    {

> > >       mdata[j] = udata[j];

> > >    }

> > >    delete[] udata;

> > >    return( mdata );

> > > }

> > > and here is the un-managed layer:

> > > void CHistogram::GrabData( int* pData, int& size )

> > > {

> > >    if( size > m_nBins )

> > >    {

> > >       size = m_nBins;

> > >    }

> > >    EnterCriticalSection( &m_csLock );

> > >    {

> > >       memcpy( pData, m_Data, size * sizeof( int ) );

> > >    }

> > >    LeaveCriticalSection( &m_csLock );

> > >    m_bDirty = false;

> > > }

> > > Here is the C# layer, with the timer set for 1 sec:

> > > private int[] m_Buffer;

> > > private CMHistogram m_Hist;

> > > private void timer_Tick(object sender, System.EventArgs e)

> > > {

> > >    if( UpdateData() )

> > >    {

> > >       Display.Invalidate();

> > >       UpdateControlBar();

> > >    }

> > > }

> > > private bool UpdateData()

> > > {

> > >    bool bDirty = m_Hist.Dirty;

> > >    if( bDirty )

> > >    {

> > >       m_Buffer = (int[])m_Hist.GrabData();

> > >       CalcStatistics();

> > >    }

> > >    return( bDirty );

> > > }

> > > Bill

> > > --

> > > http://www.componentsnotebook.com/



Wed, 25 Feb 2004 01:15:33 GMT  
 moving arrays from un-managed to managed code.
Hi Bill,

Yes, the pinned object is pinned only while a pinning pointer points to it.
Once the pinning pointer goes out of scope or is set to 0 in the program,
the object can be moved in the compaction phase of garbage collection. Any
remaining unmanaged pointers to the object should not be dereferenced then
in case they are dangling pointers, i.e. have outlived their target.

A pinning pointer is volatile by default. This prevents the optimizer from
deleting generated code for an assignment of 0 to the pinning pointer in the
source. If it were not volatile, the assignment would be treated as though
it were dead code and the object would still be pinned until its pinning
pointer went out of scope.

--
David Wolfram
Visual C++ Compiler Team

This posting is covered by the Conditions of Use:
http://www.microsoft.com/info/cpyright.htm


Quote:
> Thanks David for reminding me about __pin.

> What I am wondering about is what happens to the pinned array, is it free
to
> be moved by the garbage collector after the pointer goes out of scope?

> My latest code is:

> System::Array* CMHistogram::GrabData()

> {

>    int size = m_pHistogram->GetSize();

>    int mdata __gc[] = new int __gc[size];

>    int __pin * pmdata = &mdata[0];

>    m_pHistogram->GrabData( pmdata, size );

>    return( mdata );

> }

> void CHistogram::GrabData( int* pData, int& size )

> {

>    EnterCriticalSection( &m_csLock );

>    {

>        memcpy( pData, m_Data, size * sizeof( int ) );

>    }

>    LeaveCriticalSection( &m_csLock );

> }

> Bill

> --

> http://www.componentsnotebook.com



> > The call to memcpy should read

> > memcpy(pmdata, udata, size * sizeof(int));

> > for copying the native array. Sorry for the typo.

> > --
> > David Wolfram
> > Visual C++ Compiler Team

> > This posting is covered by the Conditions of Use:
> > http://www.microsoft.com/info/cpyright.htm



> > > Hi Bill,

> > > A way to do this which may be faster is to copy the data using native
> > code.

> > > int mdata __gc[] = new int __gc[size];

> > >    for( int j = 0 ; j < size ; j++ )

> > >    {

> > >       mdata[j] = udata[j];

> > >    }

> > > could be re-written as

> > > int mdata __gc[] = new int __gc[size];
> > > int __pin * pmdata = &pmdata[0]; // pin the managed array

> > > memcpy(udata, pmdata, size * sizeof(int));

> > > You need to pin the managed array first to prevent the possibility of
> the
> > > garbage collector moving it during the call to memcpy.

> > > --
> > > David Wolfram
> > > Visual C++ Compiler Team

> > > This posting is covered by the Conditions of Use:
> > > http://www.microsoft.com/info/cpyright.htm



> > > > I have a legacy real-time multi-threaded app, written in C++.

> > > > I eliminated all the MFC and ATL code, so all I had left was the
core
> of
> > > the
> > > > application which is time critical and mult-threaded.  Around this I
> > added
> > > a
> > > > managed C++ layer.  The GUI and remotting is being done in C#.

> > > > For updating my graphics display, as well as being able to grab a
snap
> > > shot
> > > > of the display data remotely, I need to move arrays from the
> un-managed
> > to
> > > > the managed code once per second.  I need to move 3 arrays of 4096
> > > integers
> > > > once a second.

> > > > I have come up with the following code, but was wondering if there
is
> a
> > > more
> > > > efficient way of doing this.

> > > > Here is the managed C++ layer:

> > > > System::Array* CMHistogram::GrabData()

> > > > {

> > > >    int size = m_pHistogram->GetSize();

> > > >    int* udata = new int[size];

> > > >    m_pHistogram->GrabData( udata, size );

> > > >    int mdata __gc[] = new int __gc[size];

> > > >    for( int j = 0 ; j < size ; j++ )

> > > >    {

> > > >       mdata[j] = udata[j];

> > > >    }

> > > >    delete[] udata;

> > > >    return( mdata );

> > > > }

> > > > and here is the un-managed layer:

> > > > void CHistogram::GrabData( int* pData, int& size )

> > > > {

> > > >    if( size > m_nBins )

> > > >    {

> > > >       size = m_nBins;

> > > >    }

> > > >    EnterCriticalSection( &m_csLock );

> > > >    {

> > > >       memcpy( pData, m_Data, size * sizeof( int ) );

> > > >    }

> > > >    LeaveCriticalSection( &m_csLock );

> > > >    m_bDirty = false;

> > > > }

> > > > Here is the C# layer, with the timer set for 1 sec:

> > > > private int[] m_Buffer;

> > > > private CMHistogram m_Hist;

> > > > private void timer_Tick(object sender, System.EventArgs e)

> > > > {

> > > >    if( UpdateData() )

> > > >    {

> > > >       Display.Invalidate();

> > > >       UpdateControlBar();

> > > >    }

> > > > }

> > > > private bool UpdateData()

> > > > {

> > > >    bool bDirty = m_Hist.Dirty;

> > > >    if( bDirty )

> > > >    {

> > > >       m_Buffer = (int[])m_Hist.GrabData();

> > > >       CalcStatistics();

> > > >    }

> > > >    return( bDirty );

> > > > }

> > > > Bill

> > > > --

> > > > http://www.componentsnotebook.com/



Wed, 25 Feb 2004 04:56:35 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. Passing arrays from managed to unmanaged code

2. Managed array of managed arrays of char

3. managed code vs. non-managed code

4. Referencing data from unmanaged code to managed code in C++ Wrapper class

5. calling managed code from unmanaged code

6. Calling managed code from unmanaged Code

7. Conversion of managed and unmanaged arrays

8. marshal an array from managed C++ to unmanaged C++

9. return an array from unmanaged C++ to managed C++

10. passing array from managed to unmanaged ????

11. How to Pass Array from managed to unmanaged !!??!!

12. Debugging into managed c++ DLL that is being used by unmanaged code

 

 
Powered by phpBB® Forum Software