Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / June 2007

Tip: Looking for answers? Try searching our database.

Unmanaged to managed return value

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Sharon - 24 Jun 2007 09:52 GMT
I have the following managed C++ function (VC++ 2005 (C++/CLI)

System::Array^ ManagedCppClass::GetData()
{
   BYTE* pData;
   int len;
   m_pureNativeCPPObj->GetData(pData, len); // Get the data buffer from
unmanaged class.

   array<byte>^ Arr = gcnew array<byte>(len);
   System::Runtime::InteropServices::Marshal::Copy((IntPtr)pAScan, Arr, 0,
len);
   return Arr;
}

I think this function works.
But is there a better way to that (maybe without doing the copy) ?

-------
Thanks
Sharon
Mattias Sjögren - 24 Jun 2007 19:47 GMT
>But is there a better way to that (maybe without doing the copy) ?

No you need to make a copy if you want return a managed array.

But if you know that you'll return a byte array, why not make the
return type array<byte> instead of System::Array?

Mattias

Signature

Mattias Sjögren [C# MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Sharon - 24 Jun 2007 20:36 GMT
>"Mattias Sjögren" wrote:
> But if you know that you'll return a byte array, why not make the
> return type array<byte> instead of System::Array?

Will it change the code of the function, and how, if the function will
return array<byte> instead of System::Array ?

Signature

Thanks
Sharon

Ben Voigt [C++ MVP] - 25 Jun 2007 06:42 GMT
>I have the following managed C++ function (VC++ 2005 (C++/CLI)
>
[quoted text clipped - 4 lines]
>    m_pureNativeCPPObj->GetData(pData, len); // Get the data buffer from
> unmanaged class.

What is the prototype for GetData?  That looks like you should supply the
buffer, but pData wasn't initialized.

>    array<byte>^ Arr = gcnew array<byte>(len);
>    System::Runtime::InteropServices::Marshal::Copy((IntPtr)pAScan, Arr, 0,
[quoted text clipped - 8 lines]
> Thanks
> Sharon
Sharon - 25 Jun 2007 08:11 GMT
> What is the prototype for GetData?  That looks like you should supply the
> buffer, but pData wasn't initialized.

The prototype is:

GetData(OUT BYTE*& pData, OUT int& nLength);

It allocates the buffer for the pData and should free is myself.

Signature

Thanks
Sharon

adebaene@club-internet.fr - 25 Jun 2007 11:01 GMT
> I have the following managed C++ function (VC++ 2005 (C++/CLI)
>
[quoted text clipped - 14 lines]
> I think this function works.
> But is there a better way to that (maybe without doing the copy) ?

If your native API allows you to get the data size without retrieveing
the actual data, AND to use a user-supplied buffer, you could :
- get the data size from native API.
- Allocate a managed array of the correct size.
- Pin that array (using pin_ptr).
- Pass the pinned pointer to the native API, so that it fills directly
the managed array.
- Return the managed array.

This may be more efficient if the data is big (if the data is small,
it won't make any difference - it may even make performance worst
because it means having 2 managed/native transitions instead of one).
Also, it requires that you change the unmanaged API, but this may be a
good idea anyway, since it will make your API more similar to Win32
API.

Arnaud
MVP - VC
Sharon - 25 Jun 2007 12:29 GMT
> If your native API allows you to get the data size without retrieveing
> the actual data, AND to use a user-supplied buffer, you could :
[quoted text clipped - 4 lines]
> the managed array.
> - Return the managed array.

It sounds like a good idea.
I know hot to do that in C# using unsafe and fixed.

But I can find the way to do that in managed C++ (VC++ 2005 (C++/CLI).

Maybe you can post a sample showing how it should be done?

Signature

Thanks
Sharon

Sharon - 25 Jun 2007 13:13 GMT
I think I found the way to do it:

int len = m_pureNativeCPPObj->GetDataSize();  
array<byte>^ managedArray= gcnew array<byte>(len);
System::Runtime::InteropServices::GCHandle arrHandle =        
System::Runtime::InteropServices::GCHandle::Alloc(managedArray);
IntPtr pData =
System::Runtime::InteropServices::Marshal::UnsafeAddrOfPinnedArrayElement(managedArray, 0);
m_pureNativeCPPObj->GetData((BYTE*)pData.ToPointer(), len);
arrHandle.Free();
return managedArray;

What do you think?

-------
Regards
Sharon
Ben Voigt [C++ MVP] - 25 Jun 2007 14:27 GMT
>I think I found the way to do it:
>
[quoted text clipped - 10 lines]
>
> What do you think?

Yuck!  :)

try:

pin_ptr<char> pData = &managedArray[0];

> -------
> Regards
> Sharon
Sharon - 25 Jun 2007 15:14 GMT
Yuck...

Ok... so I guess this is the nice way (-:

it should be like that:

int len = m_pureNativeCPPObj->GetDataSize();
array<byte>^ managedArray = gcnew array<byte>(len);
pin_ptr<byte> pinManagedArray = &managedArray[0];
byte* pManagedArray = pinManagedArray;
m_pureNativeCPPObj->GetData(scanLine, pixel, pManagedArray , len);
return managedArray;

No need to free nothing?

Signature

Thanks
Sharon

Ben Voigt [C++ MVP] - 25 Jun 2007 18:09 GMT
> Yuck...
>
[quoted text clipped - 6 lines]
> pin_ptr<byte> pinManagedArray = &managedArray[0];
> byte* pManagedArray = pinManagedArray;
This line wasn't needed, and is actually dangerous, if the native pointer
outlives the pinning pointer.

> m_pureNativeCPPObj->GetData(scanLine, pixel, pManagedArray , len);
> return managedArray;
>
> No need to free nothing?

No, the only allocation you did was a garbage collected array.  It
automatically unpins when the pin_ptr goes out of scope.
Sharon - 25 Jun 2007 19:36 GMT
Ok, that is great.
So I'm assuming that the way to do it is the awy I have just posted...

Signature

Thanks  a lot
Sharon

Sharon - 25 Jun 2007 19:41 GMT
>"Ben Voigt [C++ MVP]" wrote:
> > int len = m_pureNativeCPPObj->GetDataSize();
[quoted text clipped - 3 lines]
> This line wasn't needed, and is actually dangerous, if the native pointer
> outlives the pinning pointer.

Sorry, I didn't notice your remark about the unnecessary line.
So I can simply skeep the line:

byte* pManagedArray = pinManagedArray;

And leave it like that ? :

int len = m_pureNativeCPPObj->GetDataSize();
array<byte>^ managedArray = gcnew array<byte>(len);
pin_ptr<byte> pinManagedArray = &managedArray[0];
m_pureNativeCPPObj->GetData(scanLine, pixel, pinManagedArray, len);
return managedArray;

--------
Thanks again
Sharon
Ben Voigt [C++ MVP] - 26 Jun 2007 01:39 GMT
> >"Ben Voigt [C++ MVP]" wrote:
>> > int len = m_pureNativeCPPObj->GetDataSize();
[quoted text clipped - 16 lines]
> m_pureNativeCPPObj->GetData(scanLine, pixel, pinManagedArray, len);
> return managedArray;

Yup, that's exactly how pin_ptr is meant to be used.

> --------
> Thanks again
> Sharon

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.