473,770 Members | 1,953 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

MarshalAs Problems with Arrays

Below is a program that shows a test for marshaling data from a byte
array to a class structure. Unfortunately, there are two annoying
problems (bugs?) that I can't seem to get around.

The first is that if I set the Articulation array to an offset of 22
in the EntityState class instead of 24, I get the following error.
The thing is, it is properly aligned. And the amount of data to be
copied is smaller than the index of 22 anyway.

System.TypeLoad Exception: Could not load type 'Test.EntitySta te' from
assembly 'MUSE_Common, Version=7.4.0.2 5116, Culture=neutral ,
PublicKeyToken= null' because it contains an object field at offset 22
that is incorrectly aligned or overlapped by a non-object field.

The next error is that when I set the FieldOffset to 24 for the
articulations array, it runs great ... except that only the first byte
within the "other" array in DeadReckoning is set, they rest of the
bytes are 0 in the array. If I comment out the articulations array,
all the bytes of the "other" array in DeadReckoning are copied
correctly.

Help?

-------------------------------------------------

using System;
using System.Runtime. InteropServices ;

namespace MarshalTest
{
[StructLayout(La youtKind.Explic it, Size = 16)]
public struct Articulation
{
[FieldOffset(0)]
public byte parameterTypeDe signator;

[FieldOffset(1)]
public byte change;

[FieldOffset(2)]
public ushort idAttachedTo;

[FieldOffset(4)]
public uint parameterType;

[FieldOffset(8)]
public uint parameterValue1 ;

[FieldOffset(12)]
public uint parameterValue2 ;
}

[StructLayout(La youtKind.Explic it, Size = 20)]
unsafe public struct DeadReckoning
{
[FieldOffset(0)]
public byte header;

[FieldOffset(1)]
public fixed byte other[15];

[FieldOffset(16)]
public uint footer;
}

[StructLayout(La youtKind.Explic it)]
public class EntityState
{
[FieldOffset(0)]
public byte mySize;

[FieldOffset(1)]
public DeadReckoning deadRecking;

[FieldOffset(21)]
public byte temp1;

// BUG: Cannot set this offset to 22 without a runtime error.
Why?
[FieldOffset(24)]
[MarshalAs(Unman agedType.ByValA rray, ArraySubType =
UnmanagedType.S truct)]
public Articulation[] articulations;

public EntityState(byt e[] rawData)
{
int thisSize = rawData.Length;

IntPtr pData = Marshal.AllocHG lobal(thisSize) ;
Marshal.Copy(ra wData, 0, pData, thisSize);
Marshal.PtrToSt ructure(pData, this);
Marshal.FreeHGl obal(pData);

mySize = (byte)thisSize;
}

public byte[] ToRaw()
{
byte[] byteArray = new byte[mySize];
IntPtr pointer = Marshal.AllocHG lobal(mySize);
Marshal.Structu reToPtr(this, pointer, false);
Marshal.Copy(po inter, byteArray, 0, mySize);
Marshal.FreeHGl obal(pointer);
return byteArray;
}
}

class Program
{
static void Main(string[] args)
{
// Simulate raw data read from hardware
int dataSize = 22;
byte[] rawData = new byte[dataSize];
rawData[0] = (byte)dataSize;
for (int i = 0; i < dataSize; i++)
{
rawData[i] = (byte)(i + 1);
}

// Convert raw data to class
EntityState entity = new EntityState(raw Data);

// Compare original data with data stored in class
byte[] rawData2 = entity.ToRaw();

if (rawData.Length != rawData2.Length )
{
Console.WriteLi ne("**** ERROR *****: Data not the same
length.");
return;
}
bool dataIdentical = true;

// BUG: Offsets 3 - 16 are not identical
for (int i = 1; i < rawData.Length; i++)
{
if (rawData[i] != rawData2[i])
{
Console.WriteLi ne(i + ":\t" + rawData[i] +
" != " + rawData2[i] + "
*****");
dataIdentical = false;
}
else
{
Console.WriteLi ne(i + ":\t" + rawData[i] + " == "
+ rawData2[i]);
}
}
if (!dataIdentical )
{
Console.WriteLi ne("**** ERROR *****: Data not the
same.");
}
}
}
}
Jul 13 '08 #1
3 5311
O.B. wrote:
Below is a program that shows a test for marshaling data from a byte
array to a class structure. Unfortunately, there are two annoying
problems (bugs?) that I can't seem to get around.

The first is that if I set the Articulation array to an offset of 22
in the EntityState class instead of 24, I get the following error.
The thing is, it is properly aligned.
I'm afraid not. Under default packing the framework requires reference
fields to be aligned to a word boundary, that's 4 bytes in this case. So 24
bytes is OK, 22 is not. You can get around this by using SequentialLayou t
and specifying a pack size of 1 (that is, no alignment padding). Using
ExplicitLayout won't work because the packing size is ignored if you do
that. I don't know why; it doesn't seem to be an entirely logical restriction.
The next error is that when I set the FieldOffset to 24 for the
articulations array, it runs great ... except that only the first byte
within the "other" array in DeadReckoning is set, they rest of the
bytes are 0 in the array. If I comment out the articulations array,
all the bytes of the "other" array in DeadReckoning are copied
correctly.
<snip>
>
// BUG: Cannot set this offset to 22 without a runtime error.
Why?
[FieldOffset(24)]
[MarshalAs(Unman agedType.ByValA rray, ArraySubType =
UnmanagedType.S truct)]
public Articulation[] articulations;
This isn't going to work. Marshalling as .ByValArray requires that you
specify the size of the array in the SizeConst parameter. If you don't know
the size in advance, you can't use .ByValArray. So you'll have to make clear
what you're going for, here. Is "articulati ons" a variable-sized array or a
fixed-size array? If it's variable-sized, what indicates the number of
elements and how?

OK, snipping the rest of the code. These declarations work:

[StructLayout(La youtKind.Sequen tial, Pack = 1)]
public struct Articulation {
public byte parameterTypeDe signator;
public byte change;
public ushort idAttachedTo;
public uint parameterType;
public uint parameterValue1 ;
public uint parameterValue2 ;
}

[StructLayout(La youtKind.Sequen tial, Pack = 1)]
public struct DeadReckoning {
public byte header;
[MarshalAs(Unman agedType.ByValA rray, SizeConst = 15)]
public byte[] other;
public uint footer;
}

[StructLayout(La youtKind.Sequen tial, Pack = 1)]
public class EntityState {
public byte mySize;
public DeadReckoning deadRecking;
public byte temp1;

// This is probably wrong. You'll have to marshal this array manually
if it's variable-sized.
[MarshalAs(Unman agedType.ByValA rray, ArraySubType =
UnmanagedType.S truct, SizeConst = 1)]
public Articulation[] articulations;
}

It appears fixed arrays in substructures aren't marshalled correctly, or
else I just haven't found the right way to tickle the marshaller. Using a
regular array and marshalling it as .ByValArray works, though.

--
J.
Jul 13 '08 #2
On Jul 13, 4:16 pm, Jeroen Mostert <jmost...@xs4al l.nlwrote:
O.B. wrote:
Below is a program that shows a test for marshaling data from a byte
array to a class structure. Unfortunately, there are two annoying
problems (bugs?) that I can't seem to get around.
The first is that if I set the Articulation array to an offset of 22
in the EntityState class instead of 24, I get the following error.
The thing is, it is properly aligned.

I'm afraid not. Under default packing the framework requires reference
fields to be aligned to a word boundary, that's 4 bytes in this case. So 24
bytes is OK, 22 is not. You can get around this by using SequentialLayou t
and specifying a pack size of 1 (that is, no alignment padding). Using
ExplicitLayout won't work because the packing size is ignored if you do
that. I don't know why; it doesn't seem to be an entirely logical restriction.
Thanks. You are a blessing! In my real code, the offsets are not
sequential, but I can insert some "dummy" offsets to get the
sequential behavior to work.
The next error is that when I set the FieldOffset to 24 for the
articulations array, it runs great ... except that only the first byte
within the "other" array in DeadReckoning is set, they rest of the
bytes are 0 in the array. If I comment out the articulations array,
all the bytes of the "other" array in DeadReckoning are copied
correctly.

<snip>
// BUG: Cannot set this offset to 22 without a runtime error.
Why?
[FieldOffset(24)]
[MarshalAs(Unman agedType.ByValA rray, ArraySubType =
UnmanagedType.S truct)]
public Articulation[] articulations;

This isn't going to work. Marshalling as .ByValArray requires that you
specify the size of the array in the SizeConst parameter. If you don't know
the size in advance, you can't use .ByValArray. So you'll have to make clear
what you're going for, here. Is "articulati ons" a variable-sized array or a
fixed-size array? If it's variable-sized, what indicates the number of
elements and how?
It is actually variable sized. There is another attribute in the
EntityState class that specifies the number of articulations. I have
modified the test program (below) to include this attribute and how
I'm manually marshaling the data (see the ctor of EntityState). What
is odd is that the Marshal.SizeOf operation is returning a size
smaller than the actual array size returned by ToRaw(). Am I safe to
assume that the data returned by ToRaw is legit and Marshal's SizeOf
operation cannot handle dynamic arrays? Or is the SizeOf operation
correct and I am overwriting memory I shouldn't be?

using System;
using System.Runtime. InteropServices ;

namespace MarshalTest
{
[StructLayout(La youtKind.Sequen tial, Pack = 1)]
public struct Articulation
{
public byte parameterTypeDe signator;
public byte change;
public ushort idAttachedTo;
public uint parameterType;
public uint parameterValue1 ;
public uint parameterValue2 ;
}

[StructLayout(La youtKind.Sequen tial, Pack = 1)]
public struct DeadReckoning
{
public byte header;
[MarshalAs(Unman agedType.ByValA rray, SizeConst = 15)]
public byte[] other;
public uint footer;
}

[StructLayout(La youtKind.Sequen tial, Pack = 1)]
public class EntityState
{
public byte mySize; // Offset 0
public DeadReckoning deadRecking; // Offset 1
public byte numArticulation s; // Offset 21
[MarshalAs(Unman agedType.ByValA rray, ArraySubType =
UnmanagedType.S truct)]
public Articulation[] articulations;

public EntityState(byt e[] rawData)
{
// Marshal the fixed data
int fixedSize = rawData.Length 22 ? 22 : rawData.Length;

IntPtr pData = Marshal.AllocHG lobal(fixedSize );
Marshal.Copy(ra wData, 0, pData, fixedSize);
Marshal.PtrToSt ructure(pData, this);
Marshal.FreeHGl obal(pData);

// Manually marshal values for each articulation
if (numArticulatio ns 0)
{
articulations = new Articulation[numArticulation s];
byte[] tempArray = new byte[16];
for (int i = 0; i < numArticulation s; i++)
{
Array.Copy(rawD ata, 22 + i * 16, tempArray, 0,
16);
unsafe
{
fixed (byte* pData2 = tempArray)
{
articulations[i] =

(Articulation)M arshal.PtrToStr ucture((IntPtr) pData2,
typeof(Articula tion));
}
}
}
}
}

public byte[] ToRaw()
{
byte[] byteArray = new byte[mySize];
IntPtr pointer = Marshal.AllocHG lobal(mySize);
Marshal.Structu reToPtr(this, pointer, false);
Marshal.Copy(po inter, byteArray, 0, mySize);
Marshal.FreeHGl obal(pointer);
return byteArray;
}
}

class Program
{
static void Main(string[] args)
{
// Simulate raw data read from hardware
int dataSize = 54;
byte[] rawData = new byte[dataSize];
rawData[0] = (byte)dataSize;
for (int i = 1; i < dataSize; i++)
{
rawData[i] = (byte)(i + 1);
}
rawData[21] = 2; // 2 articulations

// Convert raw data to class
EntityState entity = new EntityState(raw Data);

// Why is size of resulting structure smaller than 54?
if (Marshal.SizeOf (entity) != dataSize)
{
Console.WriteLi ne("Marshal says entity size is " +
Marshal.SizeOf( entity));
}

// Compare original data with data stored in class
byte[] rawData2 = entity.ToRaw();

if (rawData.Length != rawData2.Length )
{
Console.WriteLi ne("**** ERROR *****: Data not the same
length.");
return;
}
bool dataIdentical = true;

for (int i = 1; i < rawData.Length; i++)
{
if (rawData[i] != rawData2[i])
{
Console.WriteLi ne(i + ":\t" + rawData[i] + " != "
+ rawData2[i] + " *****");
dataIdentical = false;
}
else
{
Console.WriteLi ne(i + ":\t" + rawData[i] + " == "
+ rawData2[i]);
}
}
if (!dataIdentical )
{
Console.WriteLi ne("**** ERROR *****: Data not the
same.");
}
}
}
}

Jul 14 '08 #3
O.B. wrote:
It is actually variable sized. There is another attribute in the
EntityState class that specifies the number of articulations. I have
modified the test program (below) to include this attribute and how
I'm manually marshaling the data (see the ctor of EntityState). What
is odd is that the Marshal.SizeOf operation is returning a size
smaller than the actual array size returned by ToRaw(). Am I safe to
assume that the data returned by ToRaw is legit and Marshal's SizeOf
operation cannot handle dynamic arrays? Or is the SizeOf operation
correct and I am overwriting memory I shouldn't be?
Marshal.SizeOf will only return the amount of memory the marshaller thinks
is necessary (and also what it will use to marshal data back). The
marshaller can't handle variable-sized arrays, so it will always return the
size as if the array contained one element.

I have no idea why .ToRaw() works, actually. It shouldn't. :-) Apparently
the marshaller is clever enough to marshal the array fully, but not clever
enough to adjust its size measurements for it. You are not overwriting
memory that's not yours, so it shouldn't be a problem.

--
J.
Jul 14 '08 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3126
by: Shane Mergy | last post by:
i have a program that reads through an ini file and does stuff so far the only thing i am having trouble with is the writing to the ini file. if the section is alreadey there i want to do a search for that line then all text to the next line of end of that block can someone help with this.
33
3875
by: Peter Seaman | last post by:
I understand that structures are value types and arrays and classes are reference types. But what about arrays as members of structures i.e. as in C struct x { int n; int a; }
2
8696
by: Thomas Kent | last post by:
I have a dll that is expecting a 3x3 array which I'm am using DllImport to access. In addition, this array is located in a struct that is getting passed. I'm having problems that I think are located somewhere in how I'm marshaling it. Any input would be appreciated. (examples are shortened for clarity, let me know if something more complete would be useful /*C code* typedef float RotMtxType typedef struct double ccNum RotMtxType...
2
3427
by: Robin Tucker | last post by:
I'm having problems with the IPersistFile interface. We have in house objects that support IPersistFile (and have done for years). I would like to load an object using this interface with VB.NET (note: I'm already successfully using our IPersistStorage interface for structured storage with other of our file types, but these particular file types do not support IPersistStorage). Anyway, the result I get from IPersistStorage::Load is...
0
1004
by: jg | last post by:
just for those who have to deal with legacy application that supports COM, OCX, and WINAPI(_stadcall) - c-style?, I worked out the COM interface for function out array parameters. For example ' Caller proto: ' Int32 lSz, lsz2 ' String lstrOut ' Int32 lPos
10
4995
by: David Fort | last post by:
Hi, I'm upgrading a VB6 app to VB.net and I'm having a problem with a call to a function provided in a DLL. The function takes the address of a structure which it will fill in with values. I get an error: ---------------- An unhandled exception of type 'System.NullReferenceException' occured in
1
1548
by: jsshah | last post by:
Hi I want to marshal following Win32 struct into .NEt class or struct as I want to call a native dll function from a Csharp code. The win32 struct ----------------------- typedef struct _FILE_OBJECT_ID_BUFFER {
4
9665
by: Bjarne Nielsen | last post by:
Hi all From a C# program, I need to call an unmanaged (C++) dll. The dll fills an array with variables and returns that to the C# program. When I have a fixed sized array, this works fine by using the attribute The calling program doesn't know the size of the array, so I would like the dll to dynamically expand the array, and return the right sized array.
8
4896
webroten
by: webroten | last post by:
I've been working through trying to access a C DLL from VB.NET. I've read many online postings, but I'm still having problems. Now, my error is the "Attempted to read or write protected memory" error. Here's my Structure declaration: <StructLayout(LayoutKind.Sequential, charset:=CharSet.Ansi)> _ Public Structure CONFIG_PARM <MarshalAs(UnmanagedType.LPStr)> Public address1 As String <MarshalAs(UnmanagedType.LPStr)> Public...
0
10099
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9904
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8929
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7451
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6710
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5354
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5481
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4007
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3607
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.