how to read structure which has array in c++ - c#

public struct Data
{
public long id,
public datetime time;
public string[] atts;
public string[] names;
};
Guid("3102C9D3-822E-4359-9383-9B3AF7D39F2C")]
public interface IData
{
void GetEvents([MarshalAs(UnmanagedType.LPArray)]out DataResp[] resp);
}
i want to pass and receive complex structs from C# to c++ Component and populate it into c++.
the client code is like this
Lib::Data* data;
long size = svc->GetEvents(&data);
for(size_t i = 0; i < size; ++i)
{
Lib::Data& current = data[i];
long val = current.Value;
bstr_t unit = current.Unit;
can any one help me how to read string arrays from c++ and also marshal datetime.

You will face several issues while doing so. Most of the time, you will have to decorate the structs with several attributes.
For passing strings, I wold recommend that you build a string of size expected by C++ using Stringbuilder which will be sufficient for it.
One more issue which I have faced several time is of packing. It changes the alignment of structure. To resolve, you should make sure that structs are sequentially aligned by providing proper attributes.
Further, if it requires you to pass any pointers, make sure you pin the objects before passing it otherwise the runtime will change it.

Related

What is an efficient equivalent in C# for Span<Span<T>>, which does not exist?

I was porting some older high-speed C++ code to C#, and the existing code made use of a pointer-based double-indirection pattern like this (written here in a C# syntax), using the stack as efficient temporary storage:
public struct Source {
public byte* Start;
public int Count;
}
public struct SourceSet {
public Source* Start;
public int Count;
}
Source* sources = stackalloc Source[n*k];
SourceSet* sourceSets = stackalloc SourceSet[n];
It populates the sources with sets of segments of the data, and populates the sourceSets with how many Sources are in each set.
The code works fine, but ideally, I would like to convert it to no longer use pointers and unsafe — to instead use something memory-safe like this, where each SourceSet would be populated by a .Slice() of the sources:
public struct Source {
public int Start;
public int Count;
}
Span<Source> sources = stackalloc Source[n*k];
Span<Span<Source>> sourceSets = stackalloc Span<Source>[n];
But I can't write that, because Span<Span<T>> can't exist in C# — Span<T> is a ref struct and thus can't be used as the type parameter of another Span<T>. And I can't use Memory<Memory<T>> as a replacement, because stackalloc only produces a Span<T> (or a pointer, but the goal is to avoid pointers).
(And yes, I understand that Span<Span<T>> will likely never be added to the language, because it could potentially allow the rules about span lifetimes to be violated.)
So what's a good, efficient equivalent in C# for safe double-pointer indirection on the stack, something like Span<Span<T>>, but that actually exists?

Best way to write bytes to a byte array in a struct?

I'm trying to create a packet struct that is basically a byte builder of fixed length. I have a WriteByte function written in 3 different ways. Just wondering which is best (or if there's a better way altogether) and which will keep the GC happy. BTW, I have a Position field that has to be updated when a byte(s) is written. The functions will expand to include WriteUInt16, WriteFloat etc... Not sure what the best approach is. Any advice is appreciated.
Should this be a struct? I'd like to do as little allocation as possible because these Packs will be created very frequently.
Should I put the WriteByte in the struct itself as a method (option 1), as an extension of Pack (passed by ref) (option 2), or just use a static helper class (passed by ref) (option 3)?
Here's the code:
public struct Pack
{
public byte[] Data { get; internal set; }
public int Pos { get; internal set; }
public Pack(byte opcode, ushort size)
{
++size; // make room for byte opcode
Data = new byte[2 + size]; // make room to prepend the size (ushort)
BitConverter.GetBytes(size).CopyTo(Data, 0);
Data[2] = opcode;
Pos = 3; // start writing at position 3
}
// option 1
// use: pack.WriteByte(0x01)
public void WriteByte(byte value) => Data[Pos++] = value;
}
public static class SPackExtensions
{
// option 2
// use: pack.WriteByte(0x01)
public static void WriteByte(ref this Pack pack, byte value)
{
pack.Data[pack.Pos++] = value;
}
}
public static class PackWriter
{
// option 3
// use: PackWriter.WriteByte(ref pack, 0x01)
public static void WriteByte(ref Pack pack, byte value)
{
pack.Data[pack.Pos++] = value;
}
}
Should this be a struct? I'd like to do as little allocation as possible because these Packs will be created very frequently.
Maybe. Even with a struct you will still be allocating two objects, one when converting the size to an array, and one for the array itself. So the overhead for allocating the object will probably be negligible, especially since it will probably be much smaller than the array. However, structs are recommended to be immutable, since it can be quite confusing when passing around a object if the data-array is shared, but the Pos is not.
But you should probably use BitConverter.TryWriteBytes or BinaryPrimitives.TryWriteInt16LittleEndian to avoid the allocation when writing the length.
Should I put the WriteByte in the struct itself as a method (option 1), as an extension of Pack (passed by ref) (option 2), or just use a static helper class (passed by ref) (option 3)?
The generated code should be identical, so go for whatever is easiest to use and most readable. I would probably argue for option 1. In my opinion, using extension methods or helper classes would bring little advantages in this case.
these Packs will be created very frequently
When writing performance optimized code, a good principle is avoiding allocations altogether. And as far as I can see this object would be impossible to put into a object pool and reuse, since the position parameter is not possible to reset. So I would consider basing my object around a span that is fetched from a pool of fixed size buffers.
Also, I would highly recommend that you profile your code. "Very frequently" might range from a 1hz to 10^9hz depending on context. So you should check if this is an actual problem in your particular context.

Get all values of premade struct? C#

In C# I have a VERY huge struct, and I want to iterate through it easily, instead of manually typing them.
I tried using:
Type structType = typeof(myStruct);
System.Reflection.FieldInfo[] fields = structType.GetFields();
for(int i=0; i<fields.Length-1; i++)
{
richTextBox1.Text += fields[i].Name + "\n";
}
where myStruct is the huge struct, but you can't pass variable structs to that, only the structs them selves.
Basically what I want to do is:
public struct myStruct
{
public string myName;
public int myAge;
...
...
}
//in code
myStruct a = readStructFromFile( filename );
string text = "";
foreach(field in a)
{
text += field.name + ": " + file.value;
}
That possible?
Use FieldInfo.GetValue. Bigger structs really should be classes since structs are meant to be small.
myStruct a = readStructFromFile( filename );
Type structType = typeof(myStruct);
System.Reflection.FieldInfo[] fields = structType.GetFields();
var builder = new StringBuilder();
foreach(var field in fields)
{
builder.Append(string.Format("{0} {1}\n",
field.Name,
field.GetValue(a).ToString());
}
richTextBox1.Text += builder.ToString();
My recommendation would be to write some simple code-generation routines to generate something close to the code you want and copy it to the clipboard. Then paste it into your program and make whatever little tweaks are required.
Having to write large amounts of boilerplate code usually implies a design deficiency either in what you're doing or in the language/framework you're using. Depending upon exactly what you're doing, the fault could be in either the former or the latter.
There are situations where large structures are appropriate; if each variable of some type is supposed to encapsulate a fixed collection of independent values, an exposed-field structure expresses that perfectly. Until things start getting so big as to create a risk of stack overflow, the factors which favor using a 4-field structures over a 4-field class will be even more significant with a 20-field structure versus a 20-field class.
There are some definite differences between programming with structures versus programming with classes. If one uses immutable classes, generating from a class instance a new instance which is identical except for a few fields is difficult. If one uses mutable classes, it can be difficult to ensure that every variable encapsulates its own set of independent values. Suppose one has a List<classWithPropertyX> myList, and myList[0] holds an instance where X is 3. One wishes to have myList[0] hold an instance where X is 4, but not affect the value of the X property associated with any other variable or storage location of type classWithPropertyX.
It's possible that the proper approach is
myList[0].X = 4;
but that could have unwanted side-effects. Perhaps one needs to use
myList[0] = myList[0].WithX(4);
or maybe
var temp = myList[0];
myList[0] = new classWithPropertyX(temp.this, 4, temp.that, temp.theOther, etc.);
One may have to examine a lot of code to ascertain with certainty which technique is appropriate. By contrast, if one has a List<structWithExposedFieldX> myList the proper code is:
var temp = myList[0];
temp.X = 4;
myList[0] = temp;
The only information one needs to know that's the correct approach is the fact that structWithExposedFieldX is a struct with an exposed public field X.

How to determine the size of an instance?

I have set my project to accept unsafe code and have the following helper Class to determine the size of an instance:
struct MyStruct
{
public long a;
public long b;
}
public static class CloneHelper
{
public unsafe static void GetSize(BookSetViewModel book)
{
long n = 0;
MyStruct inst;
inst.a = 0;
inst.b = 0;
n = Marshal.SizeOf(inst);
}
}
This works perfectly fine with a struct. However as soon as I use the actual class-instance that is passed in:
public unsafe static void GetSize(BookSetViewModel book)
{
long n = 0;
n = Marshal.SizeOf(book);
}
I get this error:
Type 'BookSetViewModel' cannot be marshaled as an unmanaged structure;
no meaningful size or offset can be computed.
Any idea how I could fix this?
Thanks,
Well, it really depends on what you mean by the "size" of an instance. There's the size of the single object in memory, but you usually need to think about any objects that the root object refers to. That's how much memory may be reclaimable after the root becomes eligible for garbage collection... but you can't just add them up, as those objects may be referred to by multiple other objects, and indeed there may be repeated references even within a single object.
This blog post shows some code I've used before to determine the size of the raw objects (header + fields), disregarding any extra cost due to the objects that one object refers to. It's not something I would use in production code, but it's useful for experimenting with how large an object is under varying circumstances.

Improper marshaling: C# array to a C++ unmanaged array

I have the following C# code with a structure definition (CInput), obj definition and init, and a call to a C++ (native) DLL function (that has also been written by me).
//C# code
public struct CInput
{
[MarshalAsAttribute(UnmanagedType.R8)]
public double Time;
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_R8)]
public double[] Database;
/* other similar fields*/
}
CInput Inputs = new CInput();
/* init of Inputs fields*/
int bfr = Example(ref Inputs); //'Example' being the C++ DLL call
Messagebox.Show(bfr.ToString());
There is an error in the marshaling of the second parameter, I don't know where. Then:
//C++ code
struct CInput {
double Time;
double Database[3650];
/*etc*/
}
int Example(CInput& ObjIn) {
return ObjIn.Database[0]; // just an example
}
If I'm not careful and specify only "SafeArray" in the Database marshaling I get a 'error in reading/writing memory, probably corrupt' etc.
if "Database" was marshaled as ByValArray everything is fine, the values show up correctly. Unfortunately I get an internal size exception because I have many arrays of that size, therefore I have to go for pointers - but anything with "SizeArray" will bring the following results (with the code just posted):
(from C++):
Database[0] = **0**
Database[1..etc] = values of the next parameters in the struct marshaled with ByValArray.
I think I should mention that I need the same identical structure from C# to C++, I'm not looking for anything fancy. So Array in a Struct >>> Array in a Struct.
ANY insight in reference to this would be of great value. I have been looking for hours and I don't have yet a solution.
Many thanks in advance.
As I understand your question, you can't use ByValArray with SizeConst because your real struct has a large number of such arrays which results in the stack overflowing.
You opine that maybe you need to use pointers in your structs and I agree with you. Here is how to do it.
On the C++ side you should declare each array as a pointer to the element type:
struct CInput {
double *array;
}
You may also wish to include the length of the arrays in the struct to avoid excessive amounts of hard-coded constants.
All the hard work happens on the C# side.
public struct CInput
{
public IntPtr array;
}
...
double[] theArray = new double[3650];
CInput input = new CInput();
input.array = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double))*theArray.Length);
try
{
Marshal.Copy(theArray, 0, input.array, theArray.Length);
//call your C++ function here
}
finally
{
Marshal.FreeHGlobal(input.array);
}
public struct CInput
{
public double Time;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3650)]
public double[] Database;
}
CInput Inputs = new CInput();
int bfr = Example(ref Inputs);
Edit. If you need to have dynamically allocated Database array, both C++ and C# code should be changed. In C++ Database should be defined as double*, and you need to add array length somewhere. In C# Database should be declared as IntPtr, and allocated using Marshal.AllocHGlobal method. Please correct C++ structure according to your requirements, and then C# code can be fixed according to this.

Categories

Resources