惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
O
OpenAI News
酷 壳 – CoolShell
酷 壳 – CoolShell
The GitHub Blog
The GitHub Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
W
WeLiveSecurity
Hacker News: Ask HN
Hacker News: Ask HN
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
D
Docker
F
Full Disclosure
AI
AI
罗磊的独立博客
博客园 - 【当耐特】
U
Unit 42
S
SegmentFault 最新的问题
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
P
Palo Alto Networks Blog
博客园_首页
H
Help Net Security
量子位
月光博客
月光博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
F
Fortinet All Blogs
D
DataBreaches.Net
B
Blog RSS Feed
Webroot Blog
Webroot Blog
TaoSecurity Blog
TaoSecurity Blog
S
Secure Thoughts
爱范儿
爱范儿
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
C
CERT Recently Published Vulnerability Notes
Martin Fowler
Martin Fowler
Blog — PlanetScale
Blog — PlanetScale
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Securelist

博客园 - wuhang

今天看到一个好的WEB进度条,博客园果然是富饶啊,先记录下来以备后用 c#后台写javascript前端调用 动态SQL语句根据数据库列来查询数据,动态的生成列名称 asp.net的自动跳转 【转载来的】关于句柄的一些知识 [转载来的]C# API 大全 [心情日記]亦夢亦幻 [转载来的]P/Invoke使用Win32非托管函数2 [转载来的]P/Invoke使用Win32非托管函数3 [转载来的]P/Invoke使用Win32非托管函数1 转载来的WCF基础知识问与答 转载来的,线程的基础 转载来的线程池 转载来的WinForm多线程编程篇 还是转载的C# 插件构架实战 依旧是转载来的Thread and Sync In C# (C#中的线程与同步) 转载来的C# 2.0中P/Invoke支持的几处增强 还是转载来的P/Invoke使用Win32非托管函数 转载来的P/Invoke调用,来自MSDN
【转载来的】C# 2.0中P/Invoke支持的几处增强
wuhang · 2008-05-29 · via 博客园 - wuhang

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;

struct Point2D
{
 [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
 public int[] XY;
}

struct Point2DX3
{
 [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
 public Point2D[] XYZ;
}

  事实上这是不可行的。在.NET 1.x,结构体内嵌定长数组的类型必须是primitive类型,否则不能进行marshal过程。事实上调用Marshal.SizeOf时,会弹出异常说“无法得到大小”云云

.NET 2.0把这个问题给改了(与其说是个增强,还不如说是修正了这个bug),Marshal.SizeOf(typeof(Point2DX3))现在可以正常运行,输出24 == 3 * 2 * sizeof(int)。

让Marshal.SizeOf正常工作非常重要,得不到对象的大小,内存对齐都无法保证,marshal过程根本就不可行。

此外,正常工作的Marshal.SizeOf可以使这种“序列化”方式也总能正常工作(这在我以前的blog贴过,这里是Generic版本):

unsafe class BinarySerializer
{
public static byte[] Struct2Bytes<T>(T obj)
{
int size = Marshal.SizeOf(obj);
byte[] bytes = new byte[size];
fixed (byte* pb = &bytes[0])
{
Marshal.StructureToPtr(obj, (IntPtr)pb, true);
}
return bytes;
}

public static T Bytes2Struct<T>(byte[] bytes)
{
fixed (byte* pb = &bytes[0])
{
return (T)Marshal.PtrToStructure((IntPtr)pb, typeof(T));
}
}
}

和.NET内置的序列化机制相比,这个方案效率要高得多。和.NET内置的序列化机制相似,这里需要对象或结构体内部的所有成员都能使用 Marshal.SizeOf得到其大小,对应于“对象或结构体内部的所有成员都带有[Serializable]特性或者实现了 ISerializable接口”。

PS. 这个序列化方案效率虽高,但不如.NET内置的方案可靠。.NET的编译器可以检查一个 类型能否支持序列化,而这个方案得由程序员判断Marshal.SizeOf能否工作(比如Marshal.SizeOf绝对不会知道string类型实 际占用多少内存,也就是说类型实例的大小必须是固定的才行)。