Marshalling.NET common types

Here is a C # program that tries to use Marshal.SizeOf for several types:

 using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] class AClass { } [StructLayout(LayoutKind.Sequential)] struct AStruct { } [StructLayout(LayoutKind.Sequential)] class B { AClass value; } [StructLayout(LayoutKind.Sequential)] class C<T> { T value; } class Program { static void M(object o) { Console.WriteLine(Marshal.SizeOf(o)); } static void Main() { M(new AClass()); M(new AStruct()); M(new B()); M(new C<AStruct>()); M(new C<AClass>()); } } 

The first four calls to M () are successful, but in the latter case, SizeOf throws an ArgumentException:

 "Type 'C`1[AClass]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed." 

Why? In particular, why is SizeOf throttled on C<AClass> but not B or C<AStruct> ?


EDIT: As they were asked in the comments, here is the "real world" problem that inspired this mostly academic question: I call the C API, which is basically one C function that works (pointers) to many different types of simple C structures. They all contain a common heading followed by a single field, but the type of this field differs in different structures. A flag in the header indicates the type of field. (Strange, yes, but I have to work with this).

If I could define one common type C<T> and one extern expression C # M(C<T>) , then call M(C<int>) on one line and M(C<double>) on another, I would have a short and sweet interop solution. But, given JaredPar's answer, it seems that I should make a separate C # type for each structure (although inheritance can provide a common header).

+7
generics c # interop marshalling
source share
2 answers

Usually, generators are not supported in any interaction scenario. Both P / Invoke and COM Interop will fail if you try to marshal a common type or value. Therefore, I would expect Marshal.SizeOf to be unchecked or unsupported for this scenario, as it is a marshal-specific function.

+7
source share

It is not known what size the aggregated object T will have (this would be the size of the pointer if T is a reference type and mainly any value if it is a value type).

I think you can solve this problem by setting the MarshalAs attribute in the "value" field that defines the most suitable type (for example, Unmanagedtype.SysInt). Please note that it still won’t work for so-called untranslatable types (i.e. Types for which field offsets and sizes cannot be easily derived).

But AFAIK, it is not recommended to use generics in interop.

0
source share

All Articles