目录

  1. MarshalStructureToPtr方法简介
  2. 功能及位置
  3. 语法
  4. 参数说明
  5. 异常
  6. 备注
  7. 举例
本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢
迎广大朋友指正!
                                            
                                            
具体可以参考http://msdn.microsoft.com。
                                            
                                            

Marshal.StructureToPtr方法简介

                                            
                                            

1. 功能及位置

                                            
                                            
将数据从托管对象封送到非托管内存块,属于.NET Framework 类库
命名空间:System.Runtime.InteropServices
程序集:mscorlib(在 mscorlib.dll 中)
                                            
                                            

2. 语法

                                            
                                            
C#:
      [ComVisibleAttribute(true)] public static void StructureToPtr (Object structure,IntPtr ptr,bool fDeleteOld);
C++:
      [ComVisibleAttribute(true)]public: static void StructureToPtr (Object^ structure, IntPtr ptr, bool fDeleteOld);
                                            
                                            

3. 参数说明

                                            
                                            
structure:托管对象,包含要封送的数据。该对象必须是格式化类的实例。
ptr:指向非托管内存块的指针,必须在调用此方法之前分配该指针。
fDeleteOld:设置为 true 可在执行Marshal.DestroyStructure方法前对 ptr 参数调用此方法。请注意,传递 false 可导致内存泄漏。
                                            
                                            

4. 异常

                                            
                                            
异常类型:ArgumentException
条件:structrue参数是泛型类型
                                            
                                            

5. 备注

                                            
                                            
StructureToPtr将结构的内容复制到 ptr 参数指向的预分配内存块。如果 fDeleteOld 参数为 true,则使用嵌入指
针上适当的删除 API 来删除最初由 ptr 指向的缓冲区,但该缓冲区必须包含有效数据。此方法为在镜像托管类中指
定的每个引用字段执行清理工作。
                                            
假设 ptr 指向非托管内存块。此内存块的布局由相应的托管类 structure 描述。StructureToPtr将字段值从结构封
送到指针。假设 ptr 块包含引用字段,该字段指向当前包含“abc”的字符串缓冲区。假设托管端上相应的字段是包含“vwxyz”的字符串。如果不另行通知它,StructureToPtr将分配一个新的非托管缓冲区来保存“vwxyz”,并将它挂钩到 ptr 块。这将丢弃旧缓冲区“abc”使之漂移而不将其释放回非托管堆。最后,您将得到一个孤立的缓冲区,它表示在代码中存在内存泄漏。如果将 fDeleteOld 参数设置为真,则 StructureToPtr 在继续为“vwxyz”分配新缓冲区之前释放保存“abc”的缓冲区。
                                            
                                            

6. 举例

                                            
                                            
定义PERSON结构,并将该结构的一个变量拷贝到非托管内存,再将该内存中的PERSON还原为PERSON对象,观察其内容的变化。
                                            
                                            
源代码如下:
using System;
using System.Text;
using System.Runtime.InteropServices; namespace testStructureToPtr
{
public static class define //define some constant
{
public const int MAX_LENGTH_OF_IDENTICARDID = ; //maximum length of identicardid
public const int MAX_LENGTH_OF_NAME = ; //maximum length of name
public const int MAX_LENGTH_OF_COUNTRY = ; //maximum length of country
public const int MAX_LENGTH_OF_NATION = ; //maximum length of nation
public const int MAX_LENGTH_OF_BIRTHDAY = ; //maximum length of birthday
public const int MAX_LENGTH_OF_ADDRESS = ; //maximum length of address
} public struct PERSON //person structure
{
//MarshalAs:指示如何在托管代码和非托管代码之间封送数据
//UnmanagedType:指定如何将参数或字段封送到非托管内存块
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_IDENTICARDID)]
public byte[] identicardid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_NAME)]
public byte[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_COUNTRY)]
public byte[] country;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_NATION)]
public byte[] nation;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_BIRTHDAY)]
public byte[] birthday;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_ADDRESS)]
public byte[] address;
} class testProgram
{
private static byte _fillChar = ; //the fill character //convert string to byte array in Ascii with length is len
public static byte[] CodeBytes(string str, int len)
{
if (string.IsNullOrEmpty(str))
{
str = string.Empty;
} byte[] result = new byte[len];
byte[] strBytes = Encoding.Default.GetBytes(str); //copy the array converted into result, and fill the remaining bytes with 0
for (int i = ; i < len; i++)
result[i] = ((i < strBytes.Length) ? strBytes[i] : _fillChar); return result;
} //show the person information
public static void ShowPerson(PERSON person)
{
Console.WriteLine("cardid :" + Encoding.ASCII.GetString(person.identicardid));
Console.WriteLine("name :" + Encoding.ASCII.GetString(person.name));
Console.WriteLine("country :" + Encoding.ASCII.GetString(person.country));
Console.WriteLine("nation :" + Encoding.ASCII.GetString(person.nation));
Console.WriteLine("birthday :" + Encoding.ASCII.GetString(person.birthday));
Console.WriteLine("address :" + Encoding.ASCII.GetString(person.address));
} static void Main(string[] args)
{
PERSON person;
person.identicardid = CodeBytes("", define.MAX_LENGTH_OF_IDENTICARDID);
person.name = CodeBytes("jackson", define.MAX_LENGTH_OF_NAME);
person.country = CodeBytes("China", define.MAX_LENGTH_OF_COUNTRY);
person.nation = CodeBytes("HanZu", define.MAX_LENGTH_OF_NATION);
person.birthday = CodeBytes("", define.MAX_LENGTH_OF_BIRTHDAY);
person.address = CodeBytes("Luoshan Road, Shanghai", define.MAX_LENGTH_OF_ADDRESS); int nSizeOfPerson = Marshal.SizeOf(person);
IntPtr intPtr = Marshal.AllocHGlobal(nSizeOfPerson); Console.WriteLine("The person infomation is as follows:");
ShowPerson(person); try
{
//将数据从托管对象封送到非托管内存块,该内存块开始地址为intPtr
Marshal.StructureToPtr(person, intPtr, true); //将数据从非托管内存块封送到新分配的指定类型的托管对象anotherPerson
PERSON anotherPerson = (PERSON)Marshal.PtrToStructure(intPtr, typeof(PERSON)); Console.WriteLine("The person after copied is as follows:");
ShowPerson(anotherPerson);
}
catch (ArgumentException)
{
throw;
}
finally
{
Marshal.FreeHGlobal(intPtr); //free tha memory
}
}
}
}
运行过程中的对象地址及其内容如下:
                                            
                                            
intPtr指向的内存块的内容就是程序中对person对象所赋的初值,如下图所示,共计378个字节:
 
对象person和another的地址及其identicardid成员的地址:
 
 
对象person的identicardid成员的内容,即程序中的值123456198001011111,最后的2个字节为0,图中显示的是20个元素的ASCII码的16进制数值:
 
运行结果如下:
 
 

C#——Marshal.StructureToPtr方法简介的更多相关文章

  1. 网络神器Greasemonkey(油猴子)使用方法简介+脚本分享【转载】

    推荐下,觉得这个方法有用, 今天艾薇百科来介绍一下功能强大的Greasemonkey,俗称"油猴子",Greasemonkey可以自由定制网页,实现你想要的各种功能.堪称" ...

  2. Redis Cluster搭建方法简介22211111

    Redis Cluster搭建方法简介 (2013-05-29 17:08:57) 转载▼       Redis Cluster即Redis的分布式版本,将是Redis继支持Lua脚本之后的又一重磅 ...

  3. Monte Carlo方法简介(转载)

    Monte Carlo方法简介(转载)       今天向大家介绍一下我现在主要做的这个东东. Monte Carlo方法又称为随机抽样技巧或统计实验方法,属于计算数学的一个分支,它是在上世纪四十年代 ...

  4. TabBarController创建及使用方法简介

    TabBarController创建及使用方法简介 大致讲解一下TabBarController的创建过程: 首先,我们需要一些视图,如创建UIControllerView类型的view1,view2 ...

  5. delphi操作文本文件的方法简介

    delphi操作文本文件的方法简介减小字体 增大字体 作者佚名来源不详发布时间2008-5-31 10:31:16发布人xuedelphi1 文件类型和标准过程       Delphi同Object ...

  6. iOS中常用的四种数据持久化方法简介

    iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 ...

  7. jQuery的AJAX方法简介及与其他文件$符号冲突的解决办法

    一.重要的jQuery AJAX方法简介 $.load(url) 从服务器载入数据 $.get(url,callback) 从服务器请求数据,并执行回调函数 $.post(url,data,callb ...

  8. FragmentActivity与Fragment两者交互方法简介(转)

    FragmentActivity与Fragment两者交互方法简介 分类: Fragment 2014-07-07 18:17 88人阅读 评论(0) 收藏 举报 在Android4.0后很多时候我们 ...

  9. sleep、yield、join方法简介与用法 sleep与wait区别 多线程中篇(十五)

    Object中的wait.notify.notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑 通过这三个方法完成线程在指定锁(监视器)上的等待与唤醒,这三个方法是以锁( ...

随机推荐

  1. asp.net mvc 应用Bundle(捆绑和微小)压缩技术 启用 BundleConfig 配置web.config

    从MVC4开始,我们就发现,项目中对Global.asax进行了优化,将原来在MVC3中使用的代码移到了 [App_Start]文件夹下,而Global.asax只负责初始化.其中的BundleCon ...

  2. php鼠标滚动加载

    http://www.thinkphp.cn/extend/772.html 滚动距离js判断 i = 1; //设置当前页数 $(function() { var totalpage = 6; // ...

  3. 示例详解:UIScrollview 与 Autolayout 的那点事

    前言 自从写了介绍Masonry那篇文章以后 就一直有人对UIScrollView的那个例子不是很理解 UIView *container = [UIView new]; [scrollView ad ...

  4. css控制标题长度超出部分显示省略号

    width: 50px; overflow:hidden;white-space:nowrap; text-overflow:ellipsis; 设置或检索是否使用一个省略标记(...)标示对象内文本 ...

  5. Oracle 时间差计算

    两个Date类型字段:START_DATE,END_DATE,计算这两个日期的时间差(分别以天,小时,分钟,秒,毫秒): 天: ROUND(TO_NUMBER(END_DATE - START_DAT ...

  6. python写的分析mysql binlog日志工具

    因为数据库增删改突然暴增,需要查询是那些表的操作特别频繁,写了一个用来分析bin-log的小工具,找出增删改查的表,并按照操作次数降序排列,以下是代码: 1 2 3 4 5 6 7 8 9 10 11 ...

  7. 【转】RHadoop实践系列之一:Hadoop环境搭建

    RHadoop实践系列之一:Hadoop环境搭建 RHadoop实践系列文章,包含了R语言与Hadoop结合进行海量数据分析.Hadoop主要用来存储海量数据,R语言完成MapReduce 算法,用来 ...

  8. python简单爬虫定时推送同花顺直播及荐股至邮箱

    1.初衷:实践 2.技术:python requests Template 3.思路:根据直播页面获取评价最高的前十博主,定时爬行最新的消息和实战股票 4.思路:python 编辑简单邮件html模板 ...

  9. JAVA-android 更改APP名称与图标

    首先要在你的资源文件放入你想换的图标图片拖到drawable-XX文件夹下,然后你打开AndroidManifest.xml这个配置清单文件找到application标签里的这句android:ico ...

  10. kernel启动console_init之前console不可用时发生crash的调试方法

    http://code.google.com/p/innosoc/wiki/KernelBootCrashDebug 注: 如在i386_start_kernel中加入:early_printk(&q ...