Converting native arrays to managed arrays

B

Bob Altman

Hi all,

I'm writing C++/CLI code (compiled with /clr) that accepts a native char array
(and its length) and calls a managed routine that expects an array of
System::Byte. I was just wondering if there is any magic that I'm missing that
easily marshals the native array into a managed array, or do I need to write my
own code to allocate the managed array<> and loop through it copying the native
data into the managed array?

TIA - Bob
 
M

Mark Salsbery [MVP]

Bob Altman said:
Hi all,

I'm writing C++/CLI code (compiled with /clr) that accepts a native char
array (and its length) and calls a managed routine that expects an array
of System::Byte. I was just wondering if there is any magic that I'm
missing that easily marshals the native array into a managed array, or do
I need to write my own code to allocate the managed array<> and loop
through it copying the native data into the managed array?

You can use System::Runtime::InteropServices::Marshal::Copy(), which does
the "loop through it copying " part for you :)

Mark
 
B

Bob Altman

You can use System::Runtime::InteropServices::Marshal::Copy(), which does the
"loop through it copying " part for you :)

I've tried several variations on the following code, but it complains that it
can't find an overload for Marshal::Copy that it likes. I suspect that it
doesn't like the boxed handle to an IntPtr that I think I'm trying to feed it
(by way of the gcnew IntPtr() code). How do I cast a char* to an IntPtr?

const char* value = <some array of bytes>
int size = 15;
array<unsigned char>^ myArray = gcnew array<unsigned char>(size);
Marshal::Copy(gcnew IntPtr((void*)value), myArray, 0, size);
 
M

Mark Salsbery [MVP]

Bob Altman said:
I've tried several variations on the following code, but it complains that
it can't find an overload for Marshal::Copy that it likes. I suspect that
it doesn't like the boxed handle to an IntPtr that I think I'm trying to
feed it (by way of the gcnew IntPtr() code). How do I cast a char* to an
IntPtr?

const char* value = <some array of bytes>
int size = 15;
array<unsigned char>^ myArray = gcnew array<unsigned char>(size);
Marshal::Copy(gcnew IntPtr((void*)value), myArray, 0, size);

Maybe try something like this:

const char *value = new char[100];
int size = 15;
array<unsigned char>^ myArray = gcnew array<unsigned char>(size);
Marshal::Copy(IntPtr(const_cast<void*>(static_cast<const void*>(value))),
myArray, 0, size);
delete[] value;

Mark
 
M

Mark Salsbery [MVP]

Also note that in my code sample, it ends up using the

Marshal::.Copy Method (IntPtr, array<Byte>[]()[], Int32, Int32)

form of Marshall::Copy() since the array is a Byte (unsigned char) array.

Cheers,
Mark
 
B

Bob Altman

Maybe try something like this:
const char *value = new char[100];
int size = 15;
array<unsigned char>^ myArray = gcnew array<unsigned char>(size);
Marshal::Copy(IntPtr(const_cast<void*>(static_cast<const void*>(value))),
myArray, 0, size);
delete[] value;

Thanks, that works. I didn't realize that I could create an IntPtr (not a
*reference* to an IntPtr) like that. BTW, you don't need the double cast
because you can pass a char* to the IntPtr constructor (which it widens to a
void*), so the resultant expression looks like this:

Marshal::Copy(IntPtr(const_cast<char*>(value)), myArray, 0, size);
 
M

Mark Salsbery [MVP]

Bob Altman said:
Maybe try something like this:

const char *value = new char[100];
int size = 15;
array<unsigned char>^ myArray = gcnew array<unsigned char>(size);
Marshal::Copy(IntPtr(const_cast<void*>(static_cast<const void*>(value))),
myArray, 0, size);
delete[] value;

Thanks, that works. I didn't realize that I could create an IntPtr (not a
*reference* to an IntPtr) like that. BTW, you don't need the double cast
because you can pass a char* to the IntPtr constructor (which it widens to
a void*), so the resultant expression looks like this:

Marshal::Copy(IntPtr(const_cast<char*>(value)), myArray, 0, size);

Ahh excellent, thanks :) I could have sworn I tried that and got an
error....I must have mis-typed something.

Thanks again,
Mark
 
M

Mark Salsbery [MVP]

Bob Altman said:
Maybe try something like this:

const char *value = new char[100];
int size = 15;
array<unsigned char>^ myArray = gcnew array<unsigned char>(size);
Marshal::Copy(IntPtr(const_cast<void*>(static_cast<const void*>(value))),
myArray, 0, size);
delete[] value;

Thanks, that works. I didn't realize that I could create an IntPtr (not a
*reference* to an IntPtr) like that.


Oops almost forgot - IntPtr is a value class, so you can use it that way,
and Marshal.Copy() expects it that way, not an IntPtr^.

Cheers,
Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top