Another thread on passing arrays between managed C++ and C#

  • Thread starter Thread starter Markus Stoeger
  • Start date Start date
M

Markus Stoeger

Hello,

I have an unmanaged C++ class that contains a member function similar to this
one:

void MyUnmanagedClass::get_data(unsigned char **data, int *count) {
*count = 100;
*data = new unsigned char[100];
// ... put some data into data
}

How does the managed C++ wrapper function have to look like so that I can
call it like that from C#:

MyManagedClass x = new MyManagedClass();
byte[] data;

x.get_data(out data);


What I came up with so far is:

using namespace System;

void MyManagedClass::get_data(Byte (&data)[]) {
int count;
unsigned char *tmp;

unmanaged_class->get_data(&tmp, &count);

data = new Byte[count];

for (int i = 0; i < count; i++)
data = tmp;

delete tmp;
}

.... but that requires a x.get_data(ref data); in C#, what I want is
an "out" data because I'd like to prevent the error C# gives me if I don't
initialize the ref data to null.

I'm not sure if I've even followed the right track. Whats the right way to do
that?

thanks,
Max
 
Hi Markus,
I have an unmanaged C++ class that contains a member function similar to this
one:

void MyUnmanagedClass::get_data(unsigned char **data, int *count) {
*count = 100;
*data = new unsigned char[100];
// ... put some data into data
}

How does the managed C++ wrapper function have to look like so that I can
call it like that from C#:

MyManagedClass x = new MyManagedClass();
byte[] data;

x.get_data(out data);


What I came up with so far is:

using namespace System;

void MyManagedClass::get_data(Byte (&data)[]) {
int count;
unsigned char *tmp;

unmanaged_class->get_data(&tmp, &count);

data = new Byte[count];

for (int i = 0; i < count; i++)
data = tmp;

delete tmp;
}

... but that requires a x.get_data(ref data); in C#, what I want is
an "out" data because I'd like to prevent the error C# gives me if I don't
initialize the ref data to null.

I'm not sure if I've even followed the right track. Whats the right way to do
that?


You are. You're just missing a couple of things. Try instead:

using namespace System::Runtime::InteropServices;

void get_data([Out] Byte (*data)[]) {
int count;
unsigned char *tmp;

unmanaged_class->get_data(&tmp, &count);

*data = new Byte[count];
Marshal::Copy(IntPtr(tmp), *data, 0, count);
delete tmp;
}
 
Tomas Restrepo (MVP) wrote: said:
void get_data([Out] Byte (*data)[]) {

great, thanks for the hint! I'll have to look up more information about
the Interop. namespace.

Can you recommend some book about C++.net that explains this and other
little details? I've read two fat books from Microsoft so far (Inside C#
and Programming Microsoft Windows with C#), but it seems like I need more
some times. "Programming with Managed Extensions for MSVC++.NETv2003"
looks good (from the table of contents).. any opinions on this one?

thanks,
Max
 
Hi Markus,
void get_data([Out] Byte (*data)[]) {

great, thanks for the hint! I'll have to look up more information about
the Interop. namespace.

Indeed do! The Marshal class especially has all sorts of useful little
thingies!
Can you recommend some book about C++.net that explains this and other
little details? I've read two fat books from Microsoft so far (Inside C#
and Programming Microsoft Windows with C#), but it seems like I need more
some times. "Programming with Managed Extensions for MSVC++.NETv2003"
looks good (from the table of contents).. any opinions on this one?


Unfortunately, I can't say I recommend any one specially, since I've read
few of them. Wrox "Visual C++ .NET" book has some good chapters, and a few
other ugly ones. I'd probably pick a copy of Richard Grimes VC++.NET book
without any hesitation, though, as his a great author and knows his stuff.
There's also one by some of the VC++ team guys thats probably very nice,
too, although as I say, I haven't read it myself :)
 
Back
Top