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

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
T
Threatpost
Latest news
Latest news
N
News | PayPal Newsroom
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Help Net Security
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
TaoSecurity Blog
TaoSecurity Blog
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
T
Threat Research - Cisco Blogs
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Exploit Database - CXSecurity.com
NISL@THU
NISL@THU
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Securelist
小众软件
小众软件
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
AWS News Blog
AWS News Blog
GbyAI
GbyAI
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
美团技术团队
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
博客园 - 聂微东
V2EX - 技术
V2EX - 技术
T
Troy Hunt's Blog
SecWiki News
SecWiki News
S
Secure Thoughts
B
Blog RSS Feed
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
腾讯CDC
H
Heimdal Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed

博客园 - magicdlf

[HIMCM暑期班]第4课: 扑克牌问题 [HIMCM暑期班]第3课:一个博弈问题 [HIMCM暑期班]第2课:建模 [HIMCM暑期班]第1课:概述 [C#]ASP.NET MVC 3 在线学习资料 [HIMCM]Consortium可以免费下载了! [C#]在Windows Service中使用ThreadPool [HIMCM]MathType小练习 [C#]DataGridView中使用数据绑定Enum类型 SRM 518 解题报告 SRM 522 解题报告 SRM 521 解题报告 [原创]简易版Socket聊天室 附源码 再谈C#扫雷 C#实现扫雷出炉 计算文件的散列值 zz .NET抽象工厂模式 from cnblogs 清空VSTFS cache 如何在VSTFS中设置email notification
如何通过P/Invoke返回Struct和String Array
magicdlf · 2009-03-03 · via 博客园 - magicdlf

P/Invoke提供了方便的.NET和c++ dll交互接口,通过P/Invoke可以将native的对象转化成managed object,从而享受.NET带来的种种便利.

但是,假如dll中返回的参数,不是形如int, double, bool这样可以直接转化为.NET类型的对象,又该如何使用P/Invoke呢?

比如我有这样一个接口:

Code

getGroupList返回一个嵌套struct的结构体,如何在.NET中获取该对象呢?

如果查阅MSDN,通常会得到这样的答案:

声明一个带Attribute的结构体

Code

然后写一个如下的函数,试图通过对Attribute的修饰来达到获取返回的结构体的目的.

Code

 假如你正在采用类似的方法解决问题,基本上你会得到一个Memory Corrupt的错误信息. 或许有人要说,结构体/String数组不应该作为返回值传递,而是应该放到参数中,由getGroupList来为参数赋值. 的确,有很多这样调用的例子,网上能搜到一大把,可惜的是,这样的方法只适用于定长的结构. 比如,不包括的struct,或者是定长的String数组. MSDN上有很多类似的例子,请看这里.

既然MSDN上已经有成功的例子了,那我这里要说明的是什么呢? 注意struct groupList中,groups的个数是不确定的,它是一个指像group数组的指针. .NET在Marshal的时候自然不知道如何将这样的结构体转换成.NET Object. 但是,我们可以手动写一个转换:

Code

关于IntPtr,可以在网上找一些相关的信息,这里,只要把它想象成c++中的void*类型即可. 在Main中,我们读到了一个IntPtr类型的groupList,即指向dll返回结构体的指针. 然后,在parseGroupList中,我们一步一步地解析这个指针.

struct groupList的第一个member是int count.所以,我们通过

int groupCount = Marshal.ReadInt32(groupListPtr)  把它读出来

第二个member是group*.那就可以用

IntPtr groupPtr = Marshal.ReadIntPtr(groupListPtr, 4);

读出来.注意这里4这个参数表示位移,我们之前已经读到一个int了,所以要位移4bytes.

以此类推,如此我们可以把c++中的结构体,转换成.NET中的List<Group>类型. 全归功于Marshal的强大功能.

总结

以上的方法,可以读取任何的结构体,关于如何解析字符串数组,可以看code project上的经典文章

http://www.codeproject.com/KB/cs/marshalarrayofstrings.aspx

我就是看了这篇文章后受到启发,把它扩展应用到返回struct上的.

最后还要提一下,通常情况下,还是把结构体放在返回值里,原因一,返回值要留给ErrorCode用;原因二,这样的写法通常会忘记释放内存(注意,groupList是在dll中用malloc分配的,还需要在同一个dll中free掉).一个更好的做法是设计一组GroupListAlloc/GroupListFree/int GetGroupList(GroupList*)的接口. 当然,解析的过程还是一样的. :)