By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,276 Members | 2,063 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,276 IT Pros & Developers. It's quick & easy.

Unmanaged to managed return value

P: n/a
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((I ntPtr)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
Jun 24 '07 #1
Share this Question
Share on Google+
13 Replies


P: n/a
>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<byteinstead of System::Array?
Mattias

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

P: n/a
>"Mattias Sjögren" wrote:
But if you know that you'll return a byte array, why not make the
return type array<byteinstead of System::Array?
Will it change the code of the function, and how, if the function will
return array<byteinstead of System::Array ?

--
Thanks
Sharon
Jun 24 '07 #3

P: n/a

"Sharon" <Sh*****@newsgroups.nospamwrote in message
news:C2**********************************@microsof t.com...
>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.
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((I ntPtr)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
Jun 25 '07 #4

P: n/a
"Ben Voigt [C++ MVP]" wrote:
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.

--
Thanks
Sharon
Jun 25 '07 #5

P: n/a
On Jun 24, 10:52 am, Sharon <Shar...@newsgroups.nospamwrote:
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((I ntPtr)pAScan, Arr, 0,
len);
return Arr;

}

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

Jun 25 '07 #6

P: n/a
"ad******@club-internet.fr" wrote:
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.
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?
--
Thanks
Sharon
Jun 25 '07 #7

P: n/a
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::UnsafeA ddrOfPinnedArrayElement(managedArray, 0);
m_pureNativeCPPObj->GetData((BYTE*)pData.ToPointer(), len);
arrHandle.Free();
return managedArray;

What do you think?
-------
Regards
Sharon
Jun 25 '07 #8

P: n/a

"Sharon" <Sh*****@newsgroups.nospamwrote in message
news:4E**********************************@microsof t.com...
>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::UnsafeA ddrOfPinnedArrayElement(managedArray,
0);
m_pureNativeCPPObj->GetData((BYTE*)pData.ToPointer(), len);
arrHandle.Free();
return managedArray;

What do you think?
Yuck! :)

try:

pin_ptr<charpData = &managedArray[0];
>
-------
Regards
Sharon

Jun 25 '07 #9

P: n/a
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<bytepinManagedArray = &managedArray[0];
byte* pManagedArray = pinManagedArray;
m_pureNativeCPPObj->GetData(scanLine, pixel, pManagedArray , len);
return managedArray;

No need to free nothing?
--
Thanks
Sharon
Jun 25 '07 #10

P: n/a

"Sharon" <Sh*****@newsgroups.nospamwrote in message
news:EE**********************************@microsof t.com...
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<bytepinManagedArray = &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.
Jun 25 '07 #11

P: n/a
Ok, that is great.
So I'm assuming that the way to do it is the awy I have just posted...
--
Thanks a lot
Sharon
Jun 25 '07 #12

P: n/a
>"Ben Voigt [C++ MVP]" wrote:
int len = m_pureNativeCPPObj->GetDataSize();
array<byte>^ managedArray = gcnew array<byte>(len);
pin_ptr<bytepinManagedArray = &managedArray[0];
byte* pManagedArray = pinManagedArray;
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<bytepinManagedArray = &managedArray[0];
m_pureNativeCPPObj->GetData(scanLine, pixel, pinManagedArray, len);
return managedArray;

--------
Thanks again
Sharon
Jun 25 '07 #13

P: n/a

"Sharon" <Sh*****@newsgroups.nospamwrote in message
news:90**********************************@microsof t.com...
"Ben Voigt [C++ MVP]" wrote:
int len = m_pureNativeCPPObj->GetDataSize();
array<byte>^ managedArray = gcnew array<byte>(len);
pin_ptr<bytepinManagedArray = &managedArray[0];
byte* pManagedArray = pinManagedArray;
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<bytepinManagedArray = &managedArray[0];
m_pureNativeCPPObj->GetData(scanLine, pixel, pinManagedArray, len);
return managedArray;
Yup, that's exactly how pin_ptr is meant to be used.
>
--------
Thanks again
Sharon
Jun 26 '07 #14

This discussion thread is closed

Replies have been disabled for this discussion.