目录

  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. jQuery.noConflict() 函数

    jQuery.noConflict()函数用于让出jQuery库对变量$(和变量jQuery)的控制权. 一般情况下,在jQuery库中,变量$是变量jQuery的别名,它们之间是等价的,例如jQue ...

  2. android Gui系统之SurfaceFlinger(5)---Vsync(2)

    9.Vsync第二部分 在上一篇中我们讲到,视图的刷新需要很多步骤, void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); preC ...

  3. request 、response和session的区别

    request: 1.request.getParameter("key")接受的是来自客户登陆端的数据,接受的是post或get方式传送的value. 2.请求的默认字符集是IS ...

  4. 编写Java应用程序。首先,定义一个时钟类——Clock,它包括三个int型 成员变量分别表示时、分、秒,一个构造方法用于对三个成员变量(时、分、秒) 进行初始化,还有一个成员方法show()用于显示时钟对象的时间。其次,再定义 一个主类——TestClass,在主类的main方法中创建多个时钟类的对象,使用这 些对象调用方法show()来显示时钟的时间。

    package com.hanqi.test; public class Clock { int hh; int mm; int ss; String time; Clock(int h,int m, ...

  5. Linux 性能优化工具 perf top

    1. perf perf 是一个调查 Linux 中各种性能问题的有力工具. NAME perf - Performance analysis tools for Linux SYNOPSIS per ...

  6. c#操作IIS站点

    /// <summary> /// 获取本地IIS版本 /// </summary> /// <returns></returns> public st ...

  7. Eclipse中启动tomcat报错:A child container failed during start

    我真的很崩溃,先是workspace崩了,费了好久重建的workspace,然后建立了一个小demo项目,tomcat中启动却报错,挑选其中比较重要的2条信息如下: A child container ...

  8. libsvm Minist Hog 手写体识别(源码文件)

    以上是我上一篇文章中的代码实现,里面分别用了opencv中的SVM和LibSVM,opencv的SVM用起来更方便,但貌似内部其实也是基于Libsvm,同样的参数训练出来的结果是一致的,里面有Libs ...

  9. HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)

    传送门:HDU 5895 Mathematician QSC 这是一篇很好的题解,我想讲的他基本都讲了http://blog.csdn.net/queuelovestack/article/detai ...

  10. NOIP2012pj文化之旅[floyd]

    描述 有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次,即如果他学习了某种文化,则他就不能到达其他有这种文化的国家.不同的国家可能有相同的文化.不同文化的国家 ...