目录

  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. 生成uuid

    function guid(){ if (function_exists('com_create_guid')){ return com_create_guid(); }else{ mt_srand( ...

  2. .Net Attribute详解(下) - 使用Attribute武装枚举类型

    接上文.Net Attribute详解(上)-Attribute本质以及一个简单示例,这篇文章介绍一个非常实用的例子,相信你一定能够用到你正在开发的项目中.枚举类型被常常用到项目中,如果要使用枚举To ...

  3. CMPP错误码说明

    与中国移动代码的对应关系. MI::zzzzSMSC返回状态报告的状态值为EXPIREDMJ:zzzzSMSC返回状态报告的状态值为DELETEDMK:zzzzSMSC返回状态报告的状态值为UNDEL ...

  4. ADO.Net(一)——增、删、改、查

    数据访问 对应命名空间:System.Data.SqlClient; SqlConnection:连接对象 SqlCommand:命令对象 SqlDataReader:读取器对象 CommandTex ...

  5. C#语句1:选择语句一(if else )

    语句是指程序命令,都是按照顺序执行的.语句在程序中的执行顺序称为“控制流”或“执行流”. 根据程序对运行时所收到的输入的响应,在程序每次运行时控制流可能有所不同. 注意,语句间的标点符号必须是英文标点 ...

  6. 【JSP】JSP基础学习记录(三)—— JSP的9个内置对象

    本节说一下JSP中的9个内置对象.这9个内置对象都是Servlet API接口的实例,只是JSP规范对他们进行了默认初始化(由JSP页面对应Servlet的_jspService()方法来创建这些实例 ...

  7. MYSQL 数据库导入导出命令

    MySQL命令行导出数据库 1,进入MySQL目录下的bin文件夹:cd MySQL中到bin文件夹的目录 如我输入的命令行:cd C:\Program Files\MySQL\MySQL Serve ...

  8. SQL指令中一些特别值得注意的地方

    SQL基本指令要频繁使用,要是理解错了,将来工作一定会出现很大的麻烦.今天再重新梳理一下基本的SQL语法 SQL指令 in: 这个指令,我曾经发生过把它和python中的in搞混的错误.python中 ...

  9. 烂泥:更换ESXI5.0管理网卡及管理IP地址

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 公司的服务器基本上都是在IDC机房里面的,为了更有效的利用服务器性能.所以有几台服务器,安装的是ESXI5.0做成虚拟化. 注意目前这些服务器都是双网卡 ...

  10. Mac OSX下卸载Nodejs

    有时手贱看到新版本就升级,升级后发现一堆模块不能用了,心情好慢慢调,但也有调不好的时候,只能卸载重装低版本的node了. 我的机器环境如下 1. Mac OSX 10.10.3 2. node为0.1 ...