Marshaling a struct that has a variable array with zero elements - c#

.NET 4 with 64bit. I have a C# structure that I intend to marshal to C
[StructLayout(LayoutKind.Sequential)]
public struct ParentStruct
{
public float[] FArray;
public int FArrayLength;
}
To
struct ParentStruct
{
float* FArray;
int FArrayLength;
};
The special circumstances here is the array I need to copy float[] FArray is always pinned and has 0 elements and I am only interested in copying its pointer across to native and not interested in the actual elements it has (which are none!) nor in allocating memory on the native side on the free store (heap), it will be pointing to a garbage location, this is fine.
The technical reason for doing this is that float[] FArray is pointing to an address on the GPU memory and once it is marshaled to the GPU, it will be pointing to the right data.
I want to be able to marshal this struct to C, but I am not sure what is the proper marshal way
I tried marshaling it in the current structure, I got Object contains non-primitive or non-blittable data.
I tried adding [MarshalAs(UnmanagedType.LPArray)] and I was getting Type 'Test.ParentStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
By the way, I do understand why I am getting these errors, what I really want is a way to marshal given that my array is not a variable array (but it looks like one to the interop libraries) and you can think of my struct as a fixed size.
N.B. I have to use a float[] rather than a uint or something like that because of intellisense and other constraints.

Related

Storing data for unmanaged code when using P/Invoke

I have an array of arrays of this struct (shown here in C#, but existing in C++ as well):
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
IntPtr name; //pointer to string, char* on C++ side
long pValues;
long jValues;
long eValues;
long kValues;
int cost;
};
and an algorithm in a C++ DLL that does work on it, being called from managed C# code. It's CPU-heavy, which is what necessitates this as it runs much faster in C++ than C#. The managed (C#) side never has to know the contents of the struct data, as the algorithm only returns a single array of ints.
So, how would I go about storing this data in the most efficient way (ie with the least overhead), for the lifetime of the application? I think I have it narrowed down to two options:
Initialize structs and set values in C#, pin memory with GCHandle and pass reference to C++ whenever I want to do work (see this post on Unity forums)
Initialize structs and set values in C++, have structs persist in memory on unmanaged side
So my questions are very specific:
With 1, I'm confused as to how marshalling works. It looks like in MSDN: Copying and Pinning that you are able to pass arrays of structures by pinning and passing a reference to the pinned data, without having to copy or convert any of it (and as long as the struct looks the same on both sides). Am I reading that correctly, is that how it actually works? Referring to the Unity3d forum post, I see Marshal.PtrToStructure being called; I thought that performs copying operations? As the data would be stored on the managed side in this instance, having to copy and/or convert the data every time the C++ function is called would cause a lot of overhead, unless I'm thinking that those type of operations are a lot more expensive than they actually are.
With 2, I'm wondering if it's possible to have persistence between C++ calls. To the best of my knowledge, if you're P/Invoking from a DLL, you can't have persistent data on the unmanaged side, so I can't just define and store my struct arrays there, making the only data transferred between managed and unmanaged the int array resulting from the unmanaged algorithm. Is this correct?
Thank you very much for taking the time to read and help!
If the C# code does not need to know the internals of the array and the structure, don't expose it to the C# code. Do all the work on this type in the unmanaged code and avoid marshalling overhead.
Essentially, you want to follow this basic pattern. I'm sure the details will differ, but this should give you the basic concept.
C++
MyStruct* newArray(const int len)
{
return new MyStruct[len];
}
void workOnArray(MyStruct* array, const int len)
{
// do stuff with the array
}
void deleteArray(const MyStruct* array)
{
delete[] array;
}
C#
[DllImport(dllname)]
static extern IntPtr newArray(int len);
[DllImport(dllname)]
static extern void workOnArray(IntPtr array int len);
[DllImport(dllname)]
static extern void deleteArray(IntPtr array);

Marshaling complex nested structures containing booleans

I need to do complex marshaling of several nested structures, containing variable length arrays to other structures, hence I decided to use ICustomMarshaler (see for a good JaredPar's tutorial here). But then I have a problem with a struct defined in C++ as:
typedef struct AStruct{
int32_t a;
AType* b;
int32_t bLength;
bool aBoolean;
bool bBoolean;
};
On the C# side, in the MarshalManagedToNative implementation of ICustomMarshaler I was using:
Marshal.WriteByte(intPtr, offset, Convert.ToByte(aBoolean));
offset += 1;
Marshal.WriteByte(intPtr, offset, Convert.ToByte(bBoolean));
But it was not working since I discovered that each bool in the C++ struct was taking 2 bytes. Indeed in x86 sizeof(AStruct) = 16, not 14. Ok, bool is not guaranteed to take 1 byte and so I tried with unsigned char and uint8_t but still the size is 16.
Now, I know I could use an int32 instead than a boolean, but since I care about the taken space and there are several structs containing boolean that flow to disk (I use HDF5 file format and I want to map those boolean with H5T_NATIVE_UINT8 defined in the HDF5 library that takes 1 byte), is there another way? I mean can I have something inside a struct that is guaranteed to take 1 byte?
EDIT
the same problem applies also to int16 values: depending on how many values are present because of alignment reasons the size of the struct at the end might be different from what expected. On the C# side I do not "see" the C++ struct, I simply write on the unmanaged memory by following the definition of my structs in C++. It is quite a simple process, but if I have instead to think to the real space taken by the struct (either by guessing or by measuring it) it will become more difficult and prone to errors every time I modify the struct.
This answer is in addition to what Hans Passant has said.
It might be easiest to have your structures use a fixed packing size, so you can readily predict the member layout. Keep in mind though that this could affect performance.
The rest of this answer is specific to Microsoft Visual C++, but most compilers offer their own variant of this.
To get you started, check out this SO answer #pragma pack effect and MSDN http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx
What you often use is a pragma pack(push, ...) followed by a pragma pack(pop, ...) idiom to only affect packing for the structures defined between the two pragma's:
#pragma pack(push, 4)
struct someStructure
{
char a;
int b;
...
};
#pragma pack(pop)
This will make someStructure have a predictable packing of 4 byte-alignment of each of its members.
EDIT: From the MSDN page on packing
The alignment of a member will be on a boundary that is either a multiple of n
or a multiple of the size of the member, whichever is smaller.
So for pack(4) a char will be aligned on a 1-byte boundary, a short on a 2-byte, and the rest on a 4-byte boundary.
Which value is best depends on your situation. You'll need to explicitly pack all structures you intend to access, and probably all structures that are members of structures you want to access.
sizeof(AStruct) = 16, not 14
That's correct. The struct has two extra bytes at the end that are not used. They ensure that, if you put the struct in an array, that the fields in the struct are still properly aligned. In 32-bit mode, the int32_t and AType* members require 4 bytes and should be aligned to a multiple of 4 to allow the processor to access them quickly. That can only be achieved if the structure size is a multiple of 4. Thus 14 is rounded up to 16.
Do keep in mind that this does not mean that the bool fields take 2 bytes. A C++ compiler uses just 1 byte for them. The extra 2 bytes are pure padding.
If you use Marshal.SizeOf(typeof(AStruct)) in your C# program then you'll discover that the struct you declared takes 20 bytes. This is not good and the problem you are trying to fix. The bool members are the problem, an issue that goes way, way, back to early versions of the C language. Which did not have a bool type. The default marshaling that the CLR uses is compatible with BOOL, the typedef in the winapi. Which is a 32-bit type.
So you have to be explicit about it when you declare the struct in your C# code, you have to tell the marshaller that you want the 1-byte type. Which you do by declaring the struct member as byte. Or by overriding the default marshaling:
[StructLayout(LayoutKind.Sequential)]
private struct AStruct{
public int a;
public IntPtr b;
public int bLength;
[MarshalAs(UnmanagedType.U1)]
public bool aBoolean;
[MarshalAs(UnmanagedType.U1)]
public bool bBoolean;
}
And you'll now see that Marshal.SizeOf() now returns 16. Do be aware that you have to force your program in 32-bit mode, make sure that the EXE project's Platform Target setting is x86.

Fast array copy in C#

I have a C# class that contains an int[] array (and a couple of other fields, but the array is the main thing). The code often creates copies of this class and profiling shows that the Array.Copy() call to copy this array takes a lot of time. What can I do to make it faster?
The array size is very small and constant: 12 elements. So ideally I'd like something like a C-style array: a single block of memory that's inside the class itself (not a pointer). Is this possible in C#? (I can use unsafe code if needed.)
I've already tried:
1) Using a UIn64 and bit-shifting instead of the array. (The values of each element are also very small.) This does make the copy fast, but slows down the program overall.
2) Using separate fields for each array element: int element0, int element1, int element2, etc. Again, this is slower overall when I have to access the element at a given index.
I would checkout the System.Buffer.BlockCopy if you are really concerned about speed.
http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx
Simple Example:
int[] a = new int[] {1,2,3,4,5,6,7,8};
int[] b = new int[a.Length];
int size = sizeof(int);
int length = a.Length * size;
System.Buffer.BlockCopy(a, 0, b, 0, length);
Great discussion on it over here: Array.Copy vs Buffer.BlockCopy
This post is old, but anyone in a similar situation as the OP should have a look at fixed size buffers in structs. They are exactly what OP was asking for: an array of primitive types with a constant size stored directly in the class.
You can create a struct to represent your collection, which will contain the fixed size buffer. The data will be stored directly within the struct, which will be stored directly within your class. You can copy through simple assignment.
They come with a few caveats:
They can only be used with primitive types.
They require the "unsafe" keyword on your struct.
Size must be known at compile time.
It used to be that you had to use the fixed keyword and pointers to access them, but recent changes to C# catering to performance programming have made that unnecessary. You can now work with them just like arrays.
public unsafe struct MyIntContainer
{
private fixed int myIntegers[12];
public int this[int index]
{
get => this.myIntegers[index];
set => this.myIntegers[index] = value;
}
}
There is no built-in bound checking, so it would be best for you to include that yourself on such a property, encapsulating any functionality which skips bound checks inside of a method. I am on mobile, or I would have worked that into my example.
You asked about managed arrays. If you are content to use fixed / unsafe, this can be very fast.
struct is assignable, like any primitive. Almost certainly faster than Buffer.BlockCopy() or any other method, due to the lack of method call overhead:
public unsafe struct MyStruct //the actual struct used, contains all
{
public int a;
public unsafe fixed byte buffer[16];
public ulong b;
//etc.
}
public unsafe struct FixedSizeBufferWrapper //contains _only_ the buffer
{
public unsafe fixed byte buffer[16];
}
unsafe
{
fixed (byte* bufferA = myStructA.buffer, bufferB = myStructB.buffer)
{
*((FixedSizeBufferWrapper*)bufferA) =
*((FixedSizeBufferWrapper*)bufferB);
}
}
We cast fixed-size byte buffers from each of your original structs to the wrapper pointer type and dereference each pointer SO THAT we can assign one to the other by value; assigning fixed buffers directly is not possible, hence the wrapper, which is basically zero overhead (it just affects values used in pointer arithmetic that is done anyway). That wrapper is only ever used for casting.
We have to cast because (at least in my version of C#) we cannot assign anything other than a primitive type (usually byte[]) as the buffer, and we aren't allowed to cast inside fixed(...).
EDIT: This appears get translated into a call to Buffer.Memcpy() (specifically Buffer.memcpy4() in my case, in Unity / Mono) under the hood to do the copy.

How to cast an allocated memory block to an array addressable data type.

I am trying to Marshal some data from c# to a c library. The struct that I need to pass is just a collection of pointers... something like:
struct sometype {
type1* element1;
type2** element2;
type3** element3;
type4* element4;
}
Now... I've opted to forgo the attempt to copy all of these types into c# and marshal them as structures and decided to just fill a IntPtr array with the correct data in the correct order and pass it as a pointer. As you can see, in this setup I am passing a 4 position array of pointers with positions 1 and 2 being arrays of pointers themselves. It was simple enough and indeed does work when I marshal by fixing the IntPtr array...
fixed(IntPtr* ptr = structArray){
InteropCall(ptr);
}
However, I soon realized that the c library is actually keeping a reference to the struct and after sometime, expectedly breaks when the array is moved or collected. So my solution was to allocate a block of memory using Marshal.AllocHGlobal and hold on to the reference throughout the time the c library needs that data.
So I run this:
IntPtr* pointerArray = (IntPtr*)Marshal.AllocHGlobal (IntPtr.Size * 4);
However, pointerArray always comes out as IntPtr.Zero... or i guess... just zero.
What am I doing wrong? Can I not cast a memory block into a pointer datatype? What if I wanted a byte* or int* so that I can operate on the memory block like an array?

How to know pointer to structure by it's array pointer?

I have structure:
public struct MyStruct
{
public int a;
public int b;
public byte[] mass;
}
I need:
Pass poiner to "mass" array to C++ unmanaged function.
And after it done all work it will return me pointer to "mass".
So I have the list of MyStruct. And I need to know what the MyStruct in the list contains returned "mass"(wich pointer to I have).
If I know pointer to "mass" can I reduce pointer to 8 bytes and take pointer to MyStruct?
HOW TO :
1.Get IntPtr to "mass" array?
2.Get IntPtr to MyStruct structure?
3.Get MyStruct from IntPtr?
But, do not using any copy procedure, like Marshal.Copy...
Or is there a better way to do what I need ? Can I use pointers like in C++ or IntPtr is enought, and how can I do that?
Assuming that the memory for the array is allocated by the managed code:
When you pass an array to an unmanaged function via P/Invoke, then by default the array is generally pinned in memory by the marshaller so that the memory used by the array does not have to be copied.
You should not need to use an IntPtr at all - you just need to declare the P/Invoke so that it is accepting an array parameter.
However, things are different if the unmanaged code is allocating memory to be returned to the managed code; then things get MUCH more difficult.
Assuming that's not the case, then if you can show us the "C" function declaration we might be able to come up with a P/Invoke declaration.
(I do have a feeling that your situation may be a bit more complicated though...)
Some useful links for you:
http://msdn.microsoft.com/en-us/library/z6cfh6e6%28v=vs.80%29.aspx
http://msdn.microsoft.com/en-us/library/zah6xy75.aspx
How can I pass a pointer to an array using p/invoke in C#?
And some lower level information about the optimizations that the marshaller makes when calling unmanaged code and passing arrays. Essentially, if it can it doesn't make a copy of the data at all:
http://msdn.microsoft.com/en-us/library/23acw07k%28v=vs.80%29.aspx
Take care as the structure may have some specific memory alignment.
You may be interested by this link

Categories

Resources