下面是一个C#程序,试图 Marshal.SizeOf
在几个不同的类型:
使用系统;
使用了System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)
类ACLASS {}
[StructLayout(LayoutKind.Sequential)
结构AStruct {}
[StructLayout(LayoutKind.Sequential)
B类{ACLASS值; }
[StructLayout(LayoutKind.Sequential)
类℃下T> 【T值; }
类节目
{
静态无效M(对象o){Console.WriteLine(Marshal.SizeOf(O)); }
静态无效的主要()
{
M(新ACLASS());
M(新AStruct());
M(新的B());
M(新℃下AStruct>());
M(新℃下ACLASS>());
}
}
前四个调用M()成功,但在最后一个,一下SizeOf引发ArgumentException:
类型C`1 [ACLASS]'不能被封送一个非托管的结构;任何有意义的大小或偏移,可以计算
为什么呢?特别是,为什么在一下SizeOf呛℃下ACLASS>
,但不能在 B
或 C< AStruct>
编辑:,因为它被询问的意见,这里的真实世界的问题,激发了我大部分是学术问题: 我打电话到一个C API,它基本上是C函数上操作(指针)许多不同类型的简单的C结构。都含有一个共同的报头后面是一个字段,但该字段的类型是不同的结构不同。在头一个标志表示该字段的类型。 (奇怪的,是的,但是这就是我有工作)。
如果我可以定义一个通用型 C< T>
和一个C#extern声明 M(C< T>)
,然后调用 M(C< INT>)
在同一行,而 M(C<双>)
在另一个,我想有一个简短而亲切的互操作解决方案。但考虑到JaredPar的回答,看来我必须做出一个单独的C#类型,每个结构(尽管继承可以提供通用报文头)。
泛型作为一项规则,不支持任何互操作场景。双方的P / Invoke和COM互操作的,如果你试图封送泛型类型或值将会失败。因此,我希望 Marshal.SizeOf 是未经测试或不支持此方案,因为它是一个编组特定的功能。
Here is a C# program that tries Marshal.SizeOf
on a few different 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() succeed, but on the last one, SizeOf throws an ArgumentException:
"Type 'C`1[AClass]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed."
Why? Specifically, why does SizeOf choke on C<AClass>
, but not on B
or on C<AStruct>
?
EDIT: Because it was asked about in the comments, here's the "real-world" problem that inspired this mostly-academic question: I'm calling into a C API that is basically one C function that operates on (pointers to) lots of different types of simple C structures. All contain a common header followed by one field, but the type of that field is different in different structures. A flag in the header indicates the type of the field. (Strange, yes, but that's what I have to work with).
If I could define a single generic type C<T>
and a single C# extern declaration M(C<T>)
, and then call M(C<int>)
on one line, and M(C<double>)
on another, I'd have a short and sweet interop solution. But given JaredPar's answer, it appears that I have to make a separate C# type for each structure (though inheritance can provide the common header).
Generics as a rule are not supported in any interop scenario. Both P/Invoke and COM Interop will fail if you attempt to marshal a generic type or value. Hence I would expect Marshal.SizeOf to be untested or unsupported for this scenario as it is a marshal-specific function.