C++/CLI question

A

ajk

Hi

Given an array of bytes i.e. cli::array<Byte>^ar I would like convert
from and to a structure/class

What is the best way to do this in C++/CLI ?

I have looked at using a union

class A
{ shorrt a; short b; };

union cv
{
A s;
unsigned char b[4]
}

but that isn't good way

then there is using pin_pointer

pin_pointer<Bytes> pb = &bytearray[0];
mystruct s = *reinterpret_cast<mystruct*>(pb);

but I don't want to use pin_pointers is there any better "C++/CLI"
way?

tia
Ajk
 
A

ajk

class A
{ shorrt a; short b; };

union cv
{
A s;
unsigned char b[4]

}

oh yeah i forgot, the above is not possible if A is a managed class

then I need to have a structure inside the union that is the same as
the contents of the A's members which is crappy design.
 
A

ajk

class A
{ shorrt a; short b; };
union cv
{
A s;
unsigned char b[4]

oh yeah i forgot, the above is not possible if A is a managed class

then I need to have a structure inside the union that is the same as
the contents of the A's members which is crappy design.

to answer my own question:

memorystream and binaryread can be used to readbytes and convert.
e.g.

msclr::auto_gcroot<System::IO::MemoryStream^> ms ( gcnew
System::IO::MemoryStream(bytes) );
System::IO::BinaryReader br( ms.get() );
System::Decimal dec = br.ReadDecimal();

the eq for BinaryWrite can be use to convert to a byte array

msclr::auto_gcroot<System::IO::MemoryStream^> ms( gcnew
System::IO::MemoryStream() );
System::IO::BinaryWriter bw( ms.get() );
bw.Write(dec);

hth/ajk

if somebody wonders. :)
 
J

Jeff Winn

I'm not really all that well versed on unions, they more less annoy me when
i'm trying to do managed pinvoke. Whether anyone should actually do this I'm
not sure - however here's the C# code to accomplish what you were wanting to
do. The classes would remain the same in C++/CLI, you'll just need to handle
the conversion yourself. As long as the object definitions match completely
I don't see this being a problem.

This was more to satisfy my own curiosity whether it was possible or not.
Basically, I initialized a new instance of the struct and set the members
with the values I wanted in it, allocated the memory on the heap that
matched the struct size and copied the existing struct into that pointer
ensuring to destroy the old location to prevent any memory leaks.

Afterward I just marshalled the struct back to an instance of the MyObject
class. And lastly releasing the pointer created earlier for the struct.
Since Marshal.PtrToStructure creates a new copy of the object at the pointer
specified you can safely release the old pointer without having to worry
about the garbage collector releasing the new object instance.

It's important to note the StructLayout attribute decorating the MyObject
class below. Without that, the marshaller wouldn't know what to do with the
class.

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1 {
class Program {

static void Main(string[] args) {
MyStruct struc = new MyStruct();
struc.A = 123;
struc.B = 456;

IntPtr pStruct = IntPtr.Zero;

try {
int size = Marshal.SizeOf(typeof(MyStruct));
pStruct = Marshal.AllocHGlobal(size);

Marshal.StructureToPtr(struc, pStruct, true);

MyObject obj = (MyObject)Marshal.PtrToStructure(pStruct,
typeof(MyObject));
}
finally {
if (pStruct != IntPtr.Zero) Marshal.FreeHGlobal(pStruct);
}
}
}

struct MyStruct {
public int A;
public int B;
}

[StructLayout(LayoutKind.Sequential)]
class MyObject {
int _a;
int _b;

public MyObject() {
}

public int A {
get { return this._a; }
set { this._a = value; }
}

public int B {
get { return this._b; }
set { this._b = value; }
}
}
}
 
J

Jeff Winn

Oh, and I forgot to mention this is all managed code - so my example would
work if A was a managed class from your example. :blush:)

Jeff Winn said:
I'm not really all that well versed on unions, they more less annoy me
when i'm trying to do managed pinvoke. Whether anyone should actually do
this I'm not sure - however here's the C# code to accomplish what you were
wanting to do. The classes would remain the same in C++/CLI, you'll just
need to handle the conversion yourself. As long as the object definitions
match completely I don't see this being a problem.

This was more to satisfy my own curiosity whether it was possible or not.
Basically, I initialized a new instance of the struct and set the members
with the values I wanted in it, allocated the memory on the heap that
matched the struct size and copied the existing struct into that pointer
ensuring to destroy the old location to prevent any memory leaks.

Afterward I just marshalled the struct back to an instance of the MyObject
class. And lastly releasing the pointer created earlier for the struct.
Since Marshal.PtrToStructure creates a new copy of the object at the
pointer specified you can safely release the old pointer without having to
worry about the garbage collector releasing the new object instance.

It's important to note the StructLayout attribute decorating the MyObject
class below. Without that, the marshaller wouldn't know what to do with
the class.

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1 {
class Program {

static void Main(string[] args) {
MyStruct struc = new MyStruct();
struc.A = 123;
struc.B = 456;

IntPtr pStruct = IntPtr.Zero;

try {
int size = Marshal.SizeOf(typeof(MyStruct));
pStruct = Marshal.AllocHGlobal(size);

Marshal.StructureToPtr(struc, pStruct, true);

MyObject obj = (MyObject)Marshal.PtrToStructure(pStruct,
typeof(MyObject));
}
finally {
if (pStruct != IntPtr.Zero) Marshal.FreeHGlobal(pStruct);
}
}
}

struct MyStruct {
public int A;
public int B;
}

[StructLayout(LayoutKind.Sequential)]
class MyObject {
int _a;
int _b;

public MyObject() {
}

public int A {
get { return this._a; }
set { this._a = value; }
}

public int B {
get { return this._b; }
set { this._b = value; }
}
}
}

ajk said:
Hi

Given an array of bytes i.e. cli::array<Byte>^ar I would like convert
from and to a structure/class

What is the best way to do this in C++/CLI ?

I have looked at using a union

class A
{ shorrt a; short b; };

union cv
{
A s;
unsigned char b[4]
}

but that isn't good way

then there is using pin_pointer

pin_pointer<Bytes> pb = &bytearray[0];
mystruct s = *reinterpret_cast<mystruct*>(pb);

but I don't want to use pin_pointers is there any better "C++/CLI"
way?

tia
Ajk
 

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