摘要:1、Array in stack
对于这样的struct:typedef struct { int XY[2]; } Point2D;
要在.NET为一个非托管函数传递这样一个结构体,原来得这样定义:struct Point2D
...{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
public int[] XY;
}
现在可以这么写(不过得用unsafe上下文):unsafe struct Point2D
...{
public fixed int XY[2];
}
不过这个功能还非常有限,不知道是出于什么原因考虑,只允许在strcut里面定义这样的数组,并且只能使用bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float和double这样的primitive类型。
也可以把数组作为局部变量分配在堆栈上,只是语法不太一样,那就是stackalloc关键字:int* fib = stackalloc int[100];,也要unsafe上下文。这可以提高不少效率。这是.NET 1.x就有的功能,只是似乎没人用这个...
PS. 对于只允许使用primitive类型,我认为是没道理的,最起码应该允许所有值类型的栈内数组。设计者们为啥这么考虑呢?怕堆栈溢出?据我测试.NET的堆栈空间也是1M左右,大部分情况下这么大的栈空间都被浪费了。
2、Function pointer as a return value
在.NET 1.x做P/Invoke时,对于那些回调函数,可以使用Delegate类型的参数作为函数指针传入。但有些非托管函数的返回值也是个函数指针,此时.NET 1.1变得无能为力,要调用这个函数,你得用native代码再写个包装,总之很麻烦。
.NET 2.0的System.Runtime.InteropServices.Marshal类为此需求新增了两个方法:public static Delegate GetDelegateForFunctionPointer (
IntPtr ptr,
Type t
);
public static IntPtr GetFunctionPointerForDelegate (
Delegate d
);
3、Marshal过程支持更多的类型
这是一个很细的问题,比如这样一个非托管struct:typedef struct { Point2D XYZ[3]; } Point2DX3;
对应到C#,你也许会这样写:struct......[
阅读全文]