How can I put an array inside a struct in C#? - c#

C++ code:
struct tPacket
{
WORD word1;
WORD word2;
BYTE byte1;
BYTE byte2;
BYTE array123[8];
}
static char data[8192] = {0};
...
some code to fill up the array
...
tPacket * packet = (tPacket *)data;
We can't do that as easy in C#.
Please note there is an array in the C++ structure.
Alternatively, using this source file could do the job for us, but not if there is an array in the structure.

I'm unsure of exactly what you are asking. Are you trying to get an equivalent structure definition in C# for plain old C# usage or for interop (PInvoke) purposes? If it's for PInvoke the follownig structure will work
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tPacket {
/// WORD->unsigned short
public ushort word1;
/// WORD->unsigned short
public ushort word2;
/// BYTE->unsigned char
public byte byte1;
/// BYTE->unsigned char
public byte byte2;
/// BYTE[8]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=8, ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]
public byte[] array123;
}
If you are looking for a plain old C# structure that has the same characteristics, it's unfortunately not possible to do with a struct. You cannot define an inline array of a contstant size in a C# structure nor can you force the array to be a specific size through an initializer.
There are two alternative options in the managed world.
Use a struct which has a create method that fills out the array
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tPacket {
public ushort word1;
public ushort word2;
public byte byte1;
public byte byte2;
public byte[] array123;
public static tPacket Create() {
return new tPacket() { array123 = new byte[8] };
}
}
Or alternatively use a class where you can initialize the array123 member variable directly.
EDIT OP watns to know how to convert a byte[] into a tPacket value
Unfortunately there is no great way to do this in C#. C++ was awesome for this kind of task because has a very weak type system in that you could choose to view a stream of bytes as a particular structure (evil pointer casting).
This may be possible in C# unsafe code but I do not believe it is.
Essentially what you will have to do is manually parse out the bytes and assign them to the various values in the struct. Or write a native method which does the C style casting and PInvoke into that function.

I think what you are looking for (if you are using a similar structure definition like JaredPar posted) is something like this:
tPacket t = new tPacket();
byte[] buffer = new byte[Marshal.SizeOf(typeof(tPacket))];
socket.Receive(buffer, 0, buffer.length, 0);
GCHandle pin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
t = (tPacket)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(tPacket));
pin.free();
//do stuff with your new tPacket t

It can be done with unsafe code too, although it restricts the context under which your program can run, and, naturally, introduces the possibility of security flaws.
The advantage is that you cast directly from an array to the structure using pointers and it's also maintenance-free if you are only going to add or remove fields from the struct. However, accessing the arrays require using the fixed-statement as the GC can still move the struct around in memory when it's contained in an object.
Here's some modified code of an unsafe struct I used for interpreting UDP packets:
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public unsafe struct UnsafePacket
{
int time;
short id0;
fixed float acc[3];
short id1;
fixed float mat[9];
public UnsafePacket(byte[] rawData)
{
if (rawData == null)
throw new ArgumentNullException("rawData");
if (sizeof(byte) * rawData.Length != sizeof(UnsafePacket))
throw new ArgumentException("rawData");
fixed (byte* ptr = &rawData[0])
{
this = *(UnsafePacket*)rawPtr;
}
}
public float GetAcc(int index)
{
if (index < 0 || index >= 3)
throw new ArgumentOutOfRangeException("index");
fixed (UnsafePacket* ptr = &acc)
{
return ptr[index];
}
}
public float GetMat(int index)
{
if (index < 0 || index >= 9)
throw new ArgumentOutOfRangeException("index");
fixed (UnsafePacket* ptr = &mat)
{
return ptr[index];
}
}
// etc. for other properties
}
For this kind of code it is extremely important to check that the length of the array perfectly matches the size of the struct, otherwise you'll open for some nasty buffer overflows. As the unsafe keyword has been applied to the whole struct, you don't need to mark each method or codeblock as separate unsafe statements.

You can place what looks to the outside world like an array of fixed size within a safe structure by writing functions within the structure for access. For example, here is a fixed 4 by 4 double precision array within a safe structure:
public struct matrix4 // 4 by 4 matrix
{
//
// Here we will create a square matrix that can be written to and read from similar
// (but not identical to) using an array. Reading and writing into this structure
// is slower than using an array (due to nested switch blocks, where nest depth
// is the dimensionality of the array, or 2 in this case). A big advantage of this
// structure is that it operates within a safe context.
//
private double a00; private double a01; private double a02; private double a03;
private double a10; private double a11; private double a12; private double a13;
private double a20; private double a21; private double a22; private double a23;
private double a30; private double a31; private double a32; private double a33;
//
public void AssignAllZeros() // Zero out the square matrix
{ /* code */}
public double Determinant() // Common linear algebra function
{ /* code */}
public double Maximum() // Returns maximum value in matrix
{ /* code */}
public double Minimum() // Minimum value in matrix
{ /* code */}
public double Read(short row, short col) // Outside read access
{ /* code */}
public double Read(int row, int col) // Outside read access overload
{ /* code */}
public double Sum() // Sum of 16 double precision values
{
return a00 + a01 + a02 + a03 + a10 + a11 + a12 + a13 + a20 + a21 + a22 + a23 + a30 + a31 + a32 + a33;
}
public void Write(short row, short col, double doubleValue) // Write access to matrix
{ /* code */}
public void Write(int row, int col, double doubleValue) // Write access overload
{ /* code */}
}

Related

Convert template C++ to C#

i have template in project c++ and i want to translate code to c# now, and i get some errors in template c#.
In C++
template<typename T>
struct pares
{
DWORD64 first;
T* second;
};
template<typename T>
struct hash_node
{
pares<T> mValue;
hash_node<T>* mpNext;
};
template<typename T>
struct hashtable
{
DWORD64 vtable;
hash_node<T>** mpBucketArray;
unsigned int mnBucketCount;
unsigned int mnElementCount;
//...
};
template<typename T>
struct hashtable_iterator
{
hash_node<T>* mpNode;
hash_node<T>** mpBucket;
};
In C#
public class pair<T>
{
public Int64 first;
public T second;
}
public class hash_node<T>
{
public pair<T> mValue = new pair<T>();
public hash_node<T> mpNext;
}
public class hashtable<T>
{
public Int64 vtable;
public hash_node<T>[] mpBucketArray;
public int mnBucketCount;
public int mnElementCount;
}
public class hashtable_iterator<T>
{
public hash_node<T> mpNode;
public hash_node<T> mpBucket;
}
Inside a function in c++ project i have this line , its fine without error:
hashtable<DWORD64>* table = (hashtable<DWORD64>*)(pObfuscationMgr + 8);
But in C# get error:
Cannot convert type 'long' to 'hashtable'
hashtable<Int64> table = (hashtable<Int64>)(pObfuscationMgr + 8);
The reason for the error is that you are telling the compiler to interpret a memory position as a hashtable<> object. This works in C++ because you have the tool to do that: pointers. A pointer is just a memory position with an associated type.
You have a memory block pointed by pObfuscationMgr, and you intend to create a pointer to a hashtable<> and this way understand the contents at that memory position (plus eight) as a hashtable<>.
If you do a verbatim translation to C#:
hashtable<Int64> table = (hashtable<Int64>)(pObfuscationMgr + 8);
Pointers are lost in that translation, because there are no pointers in C#. So, now pObfuscationMgr is now just a long, and hence the compiler's error: you cannot transform a long into a hashtable<>.
For example, you can do this in C or C++:
void foo()
{
char buffer[1024];
int * ptr1 = (int *) &buffer;
int * ptr2 = (int *) ( &buffer + 8 );
*ptr1 = 40;
*ptr1 += 2;
*ptr2 = 5;
*ptr2 *= 2;
printf( "%d\n", *ptr1 );
printf( "%d\n", *ptr2 );
}
In the code above, you are creating a buffering area in the stack, in the shape of a char array. Then you create the ptr1 and ptr2 pointers, and make them point to the beginning of that area and to the beginning of that area plus eight. Then you can manage both pointers as if they were pointing to real variables. That is more or less similar to what the original code does.
You won't be successful by doing a verbatim translation of C++ code into C#. Of course that translation is achievable, but having a deep knowledge about memory in C++ and how to represent that in C#, i.e., doing a real translation.
Hope this (somehow) helps.

How to convert/cast (at bit level) Struct from other with the same size?

suppose I have two 128-bit structures ...
struct OldInfo
{
int Id,
int Tag,
long Code
}
struct NewInfo
{
short Kind,
long Key,
int Data,
short Value
}
and then I want to...
var old = new OldInfo();
. . .
var new = (NewInfo)old; // Cast bit by bit as they have same size
So, how to cast (at bit level) on struct from another of same size, fast?
Maybe using some bitwise operation? or 'unsafe'? or aplying 'StructLayout' attribute?
Thanks for your time!
As written the two structures don't have the same size. This because the NewInfo.Key is a long so normally is aligned on 8 byte boundary... So there is a "gap" of 6 empty bytes between Kind and Key (you can try doing a Marshal.SizeOf(typeof(NewInfo))). But you can apply a [StructLayout] attribute to fix this.
struct OldInfo
{
public int Id;
public int Tag;
public long Code;
}
[StructLayout(LayoutKind.Auto, Pack = 1)]
struct NewInfo
{
public short Kind;
public long Key;
public int Data;
public short Value;
}
Now... There is a totally unsafe System.Runtime.CompilerServices.Unsafe library of Microsoft:
int s1 = Unsafe.SizeOf<OldInfo>();
int s2 = Unsafe.SizeOf<NewInfo>();
Debug.Assert(s1 == s2);
OldInfo oi = new OldInfo { Id = 1, Tag = 2, Code = 3 } ;
NewInfo ni = Unsafe.As<OldInfo, NewInfo>(ref oi);
This library is unsafe enough that it won't tell you if the size of the structures are different :-) It will copy and perhaps overwrite something important in memory :-)

Return list of points (x,y,z) from C to C# using PInvoke

I need to return a list of points i have from a C dll to a C# application using PInvoke. These are points in 3 dimensions [x,y,z]. The number of points varies by what kind of model it is. In C i handle this a linked list of structs. But I don't see how i can pass this on to C#.
The way I see it, I have to return a flexible two dimensional array, probably in a struct.
Any suggestions to how this can be done? Both ideas on how to return it in C and how to access it in C# are highly appreciated.
A linked list of structs could be passed back, but it would be quite a hassle to deal with, as you would have to write code to loop through the pointers, reading and copying the data from native memory into managed memory space. I would recommend a simple array of structs instead.
If you have a C struct like the following (assuming 32-bit ints)...
struct Point
{
int x;
int y;
int z;
}
... then you'd represent it nearly the same way in C#:
[StructLayout(LayoutKind.Sequential]
struct Point
{
public int x;
public int y;
public int z;
}
Now to pass an array back, it would be easiest to have your native code allocate the array and pass it back as a pointer, along with another pointer specifying the size in elements.
Your C prototype might look like this:
// Return value would represent an error code
// (in case something goes wrong or the caller
// passes some invalid pointer, e.g. a NULL).
// Caller must pass in a valid pointer-to-pointer to
// capture the array and a pointer to capture the size
// in elements.
int GetPoints(Point ** array, int * arraySizeInElements);
The P/Invoke declaration would then be this:
[DllImport("YourLib.dll")]
static extern int GetPoints(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out Point[] array,
out int arraySizeInElements);
The MarshalAs attribute specifies that the array should be marshaled using the size specified in the second parameter (you can read more about this at MSDN, "Default Marshaling for Arrays").
If you use this approach, note that you must use CoTaskMemAlloc to allocate the native buffer as this is what the .NET marshaler expects. Otherwise, you will get memory leaks and/or other errors in your application.
Here is a snippet from the simple example I compiled while verifying my answer:
struct Point
{
int x;
int y;
int z;
};
extern "C"
int GetPoints(Point ** array, int * arraySizeInElements)
{
// Always return 3 items for this simple example.
*arraySizeInElements = 3;
// MUST use CoTaskMemAlloc to allocate (from ole32.dll)
int bytesToAlloc = sizeof(Point) * (*arraySizeInElements);
Point * a = static_cast<Point *>(CoTaskMemAlloc(bytesToAlloc));
*array = a;
Point p1 = { 1, 2, 3 };
a[0] = p1;
Point p2 = { 4, 5, 6 };
a[1] = p2;
Point p3 = { 7, 8, 9 };
a[2] = p3;
return 0;
}
The managed caller can then deal with the data very simply (in this example, I put all the interop code inside a static class called NativeMethods):
NativeMethods.Point[] points;
int size;
int result = NativeMethods.GetPoints(out points, out size);
if (result == 0)
{
Console.WriteLine("{0} points returned.", size);
foreach (NativeMethods.Point point in points)
{
Console.WriteLine("({0}, {1}, {2})", point.x, point.y, point.z);
}
}

How to map a C union with const char* to C# struct?

In a callback function from a native library, I need to access an array of espeak_EVENT.
The problem is the UNION statement in the original C code:
typedef struct {
espeak_EVENT_TYPE type;
unsigned int unique_identifier; // message identifier (or 0 for key or character)
int text_position; // the number of characters from the start of the text
int length; // word length, in characters (for espeakEVENT_WORD)
int audio_position; // the time in mS within the generated speech output data
int sample; // sample id (internal use)
void* user_data; // pointer supplied by the calling program
union {
int number; // used for WORD and SENTENCE events. For PHONEME events this is the phoneme mnemonic.
const char *name; // used for MARK and PLAY events. UTF8 string
} id;
} espeak_EVENT;
I have
[StructLayout(LayoutKind.Explicit)]
public struct espeak_EVENT
{
[System.Runtime.InteropServices.FieldOffset(0)]
public espeak_EVENT_TYPE type;
[System.Runtime.InteropServices.FieldOffset(4)]
public uint unique_identifier; // message identifier (or 0 for key or character)
[System.Runtime.InteropServices.FieldOffset(8)]
public int text_position; // the number of characters from the start of the text
[System.Runtime.InteropServices.FieldOffset(12)]
public int length; // word length, in characters (for espeakEVENT_WORD)
[System.Runtime.InteropServices.FieldOffset(16)]
public int audio_position; // the time in mS within the generated speech output data
[System.Runtime.InteropServices.FieldOffset(20)]
public int sample; // sample id (internal use)
[System.Runtime.InteropServices.FieldOffset(24)]
public IntPtr user_data; // pointer supplied by the calling program
[System.Runtime.InteropServices.FieldOffset(32)]
public int number;
[System.Runtime.InteropServices.FieldOffset(32)]
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string name;
}
And then
public static Int32 SynthCallback(IntPtr wav, Int32 numsamples, IntPtr eventsParameter)
{
if (wav == IntPtr.Zero)
return 0;
int j=0;
while(true)
{
System.IntPtr ptr = new IntPtr(
(
eventsParameter.ToInt64()
+ (j *
System.Runtime.InteropServices.Marshal.SizeOf(typeof(cEspeak.espeak_EVENT))
)
)
);
if(ptr == IntPtr.Zero)
Console.WriteLine("NULL");
cEspeak.espeak_EVENT events = (cEspeak.espeak_EVENT) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(cEspeak.espeak_EVENT));
if(events.type == cEspeak.espeak_EVENT_TYPE.espeakEVENT_SAMPLERATE)
{
Console.WriteLine("Heureka");
}
break;
//Console.WriteLine("\t\t header {0}: address={1}: offset={2}\n", j, info.dlpi_phdr, hdr.p_offset);
++j;
}
if(numsamples > 0)
{
byte[] wavbytes = new Byte[numsamples * 2];
System.Runtime.InteropServices.Marshal.Copy(wav, wavbytes, 0, numsamples*2);
bw.Write(wavbytes, 0, numsamples*2);
}
return 0;
}
But it always fails on
cEspeak.espeak_EVENT events = (cEspeak.espeak_EVENT) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(cEspeak.espeak_EVENT));
However, when I remove
[System.Runtime.InteropServices.FieldOffset(32)][System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string name;
From espeak_event, then it works.
How can I make this work without removing the string in the union ?
I need to access it in the callback function.
Edit:
And btw, what happens to the field offsets if I let it run on x64, and the size of " public IntPtr user_data;" changes from 32 to 64 bit ?
Hm, thinking about it, is fieldoffset 32 correct ?
Seems I mixed-up the pointer size when thinking about x64.
That might very well be another bug.
Hm, union with int and char*, my guess is they never compiled it for x64.
Because sizof(int) is 32 bit on a x64 Linux system.
Declare name as IntPtr rather than string and then use Marshal.PtrToStringAnsi to get it into a string variable.
I'm ignoring the fact that the string contents are UTF-8. If your text is pure ASCII that's fine. If not then you need to copy to a byte[] array and then translate from UTF-8 with Encoding.UTF8.GetString.
Now this might sound overly work intensive, but whenever I'm a situation where I must access through a binding some C structure utilizing C specific features (like unions or void* pointers), I normally write a set of get/set functions from/to the target language native (marshalling) types in C and provide those through the binding and keep the structure itself opaque.
Can you first marshal a struct with only espeak_EVENT_TYPE type? Then you could choose one of two structs depending on what you expect to find in the contents of the union: one having only int number and one having only const char *name.

converting between struct and byte array

his question is about converting between a struct and a byte array. Many solutions are based around GCHandle.Alloc() and Marshal.StructureToPtr(). The problem is these calls generate garbage. For example, under Windows CE 6 R3 about 400 bytes of garbarge is made with a small structure. If the code below could be made to work the solution could be considered cleaner. It appears the sizeof() happens too late in the compile to work.
public struct Data
{
public double a;
public int b;
public double c;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct DataWrapper
{
private static readonly int val = sizeof(Data);
[FieldOffset(0)]
public fixed byte Arr[val]; // "fixed" is to embed array instead of ref
[FieldOffset(0)]
public Data; // based on a C++ union
}
You can in fact use the constant value 1 as the size of the fixed array in DataWrapper. There is no bounds checking when accessing an unsafe fixed array nor is there any mechanism to request its length at runtime. The presence of the Data member at offset 0 is enough to ensure that you can actually read and write sizeof(Data) bytes to/from DataWrapper.Arr.
With that said, a more straight forward solution would be to cast a Data* pointer to byte* as follows:
unsafe {
Data d = new Data();
d.a = 125.5;
d.b = 0x7FEEDDEE;
d.c = 130.0;
byte* bytes = (byte*)&d;
for (int i = 0; i < sizeof(Data); i++) {
Console.WriteLine(i + ": " + bytes[i]);
}
}

Categories