Click here to Skip to main content
15,896,557 members

value type structures array elements in C++/C#

vamoose asked:

Open original thread
Hi All,

After a lot of searching the web and trying different things, I am still no closer to solving the following:

I have written a c++ managed dll that is supposed to act as a wrapper for legacy c code. The c code uses a lot of structures that is filled with data from a host system.

My final GUI application that needs to process this data is written in C#

My c structure:
C++
typedef struct
{
	unsigned short	u16_RecordType;
	unsigned short	u16_RecordCode;
	char		c_MessageType;
	unsigned char	uc_Filler;
	unsigned long	u32_MessageCode;
	char		c_InfoMessage[3][24];
	unsigned short	u16_CheckSum;

} THE_C_STRUCT;


Which I have declared in my c++ dll as:
C++
[StructLayoutAttribute(LayoutKind::Sequential, Pack=1)]
public value struct MyManagedStruct
{
	unsigned short	u16_RecordType;
	unsigned short	u16_RecordCode;
	char		c_MessageType;
	unsigned char	uc_Filler;
	unsigned long	u32_MessageCode;
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=72)]
	static char	^c_MessageLines = gcnew char[3][24]; 
	unsigned short	u16_CheckSum;
};


And then the c++ code to get me the data using the legacy C function. Notice that I use a generic function to convert the byte array of data to the structure object. This function has up to now worked perfectly on all other structures.

C++
Object ^MyWrapperClass::ByteArrayToStructure(array<unsigned char> ^bytearray, int offset, Type ^objType)
{
    Object ^returnObj;
    int len = Marshal::SizeOf(objType);
    IntPtr intPtr = Marshal::AllocHGlobal(len);
            
    Marshal::Copy(bytearray, offset, intPtr, len);
    returnObj = Marshal::PtrToStructure(intPtr, objType);
    Marshal::FreeHGlobal(intPtr);

    return returnObj;
}

int MyWrapperClass::GetStructure([Out] Wrapper_Record %p_s_RecordData)
{
	int i_RC;
    
    Type ^t_RecordType = p_s_RecordData.GetType();
    array<unsigned char> ^uc_RecordDataArr = gcnew array<unsigned char>(Marshal::SizeOf(p_s_RecordData));
    pin_ptr<unsigned char>	pp_RecordBuffer = &uc_RecordDataArr[0];

    // call the C function to get the data into the byte array
    i_RC = LC_GetRecord(pp_RecordBuffer);
    if (I_RC == SUCCESS)
    	p_s_RecordData = (Wrapper_Record)ByteArrayToStructure(uc_RecordDataArr, 0, t_RecordType);
    	
    return I_RC;
}


Finally, I am calling the dll from my c# code:
C#
Wrapper_Record wrapperRecord;
MyWrapperClass s = new MyWrapperClass();

int i = s.GetStructure(out wrapperRecord);


My problem:
1. When debugging the function ByteArrayToStructure(), the value of len is 10! (the structure is supposed to be 84 bytes?)
2. I suspected the array in the structure is the problem, so I changed the structure to:
C++
[StructLayoutAttribute(LayoutKind::Sequential, Size=72, Pack=1)]
public value struct Message_Lines
{
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=24)]
	//static array<char>^ c_MessageLine1; 
	static char	^c_MessageLine1 = gcnew char[24]; 
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=24)]
	//static array<char>^ c_MessageLine2; 
	static char	^c_MessageLine2 = gcnew char[24]; 
	[MarshalAs(UnmanagedType::ByValArray,SizeConst=24)]
	//static array<char>^ c_MessageLine3; 
	static char	^c_MessageLine3 = gcnew char[24]; 
};

[StructLayoutAttribute(LayoutKind::Sequential, Pack=1)]
public value struct MyManagedStruct
{
	unsigned short		u16_RecordType;
	UINT16			u16_RecordCode;
	CHAR			c_MessageType;
	unsigned char		uc_Filler;
	UINT16			u32_MessageCode;
	//[MarshalAs(UnmanagedType::ByValArray,SizeConst=72)]
	//static char	^c_MessageLines = gcnew char[3][24]; 
	Message_Lines		s_MessagLines;
	unsigned short		u16_CheckSum;
};


So the length issue was solved, but when looking at my output object, the structure fields are populated, but the Message_Lines structure values are all zero. I confirmed in debugging that the byte array is populated correctly before calling ByteArrayToStructure().

What is the correct way of implementing this structure and properly populate the return object?
Am I using Marshal::PtrToStructure correctly?
Does anybody have a good link where I can learn more about marshalling structures that have arrays as elements?
Please help!
Tags: C++, C, C#, Unmanaged, Managed

Plain Text
ASM
ASP
ASP.NET
BASIC
BAT
C#
C++
COBOL
CoffeeScript
CSS
Dart
dbase
F#
FORTRAN
HTML
Java
Javascript
Kotlin
Lua
MIDL
MSIL
ObjectiveC
Pascal
PERL
PHP
PowerShell
Python
Razor
Ruby
Scala
Shell
SLN
SQL
Swift
T4
Terminal
TypeScript
VB
VBScript
XML
YAML

Preview



When answering a question please:
  1. Read the question carefully.
  2. Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  3. If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
  4. Don't tell someone to read the manual. Chances are they have and don't get it. Provide an answer or move on to the next question.
Let's work to help developers, not make them feel stupid.
Please note that all posts will be submitted under the http://www.codeproject.com/info/cpol10.aspx.



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900