. 功能及位置
将数据从托管对象封送到非托管内存块,属于.NET Framework 类库
命名空间:System.Runtime.InteropServices
程序集:mscorlib(在 mscorlib.dll 中) . 语法
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); . 参数说明
structure:托管对象,包含要封送的数据。该对象必须是格式化类的实例。
ptr:指向非托管内存块的指针,必须在调用此方法之前分配该指针。
fDeleteOld:设置为 true 可在执行Marshal.DestroyStructure方法前对 ptr 参数调用此方法。请注意,传递 false 可导致内存泄漏。 . 异常
异常类型:ArgumentException
条件:structrue参数是泛型类型 . 备注
StructureToPtr将结构的内容复制到 ptr 参数指向的预分配内存块。如果 fDeleteOld 参数为 true,则使用嵌入指
针上适当的删除 API 来删除最初由 ptr 指向的缓冲区,但该缓冲区必须包含有效数据。此方法为在镜像托管类中指
定的每个引用字段执行清理工作。 假设 ptr 指向非托管内存块。此内存块的布局由相应的托管类 structure 描述。StructureToPtr将字段值从结构封
送到指针。假设 ptr 块包含引用字段,该字段指向当前包含“abc”的字符串缓冲区。假设托管端上相应的字段是包含“vwxyz”的字符串。如果不另行通知它,StructureToPtr将分配一个新的非托管缓冲区来保存“vwxyz”,并将它挂钩到 ptr 块。这将丢弃旧缓冲区“abc”使之漂移而不将其释放回非托管堆。最后,您将得到一个孤立的缓冲区,它表示在代码中存在内存泄漏。如果将 fDeleteOld 参数设置为真,则 StructureToPtr 在继续为“vwxyz”分配新缓冲区之前释放保存“abc”的缓冲区。 . 举例
定义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
}
}
}
} . 分析及扩展
结构体:
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;
} A. 通过获取Person信息的函数返回的指针,再将该指针转换为结构体,并显示结构体中的内容
a. 获取Person信息的函数
//获取 Person信息
[DllImport("person.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetPerson(IntPtr pEngine); b. 使用指针定义一个变量,来获取一个返回值为该指针的函数
IntPtr Person = GetPerson(pEngine); c. 将指针变量装换为结构体,操作如下:
PERSON anotherPerson = (PERSON)Marshal.PtrToStructure(intPtr, typeof(PERSON)); d. 通过ShowPerson(PERSON person)函数,用来打印输出信息
Console.WriteLine("cardid :" + Encoding.ASCII.GetString(anotherPerson.identicardid)); B. 通过定义结构体,并赋值结构体中的数据,再将结构体转为指针数据,并将指针传入到SetPerson信息的函数中
a. 设置Person信息的函数
//获取 Person信息
[DllImport("person.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SetPerson(IntPtr pEngine); b. 定义结构体,并赋值结构体中的数据
PERSON person = new 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); c. 将结构体转为指针数据 int nSizeOfPerson = Marshal.SizeOf(person); //定义指针长度
IntPtr personX = Marshal.AllocHGlobal(nSizeOfPerson); //定义指针
Marshal.StructureToPtr(person, personX, true); //将结构体person转为personX指针 d. 将指针传入到SetPerson函数中
SetPerson(personX);
 

C#将结构体和指针互转的方法的更多相关文章

  1. 【学习笔记】【C语言】指向结构体的指针

    1.指向结构体的指针的定义 struct Student *p;  2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...

  2. c语言中较常见的由内存分配引起的错误_内存越界_内存未初始化_内存太小_结构体隐含指针

    1.指针没有指向一块合法的内存 定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内浅显的例子就不举了,这里举几个比较隐蔽的例子. 1.1结构体成员指针未初始化 struct stude ...

  3. C语言结构体和指针

    指针也可以指向一个结构体,定义的形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例: struct stu{ char *name; //姓名 int num; //学号 ...

  4. 37深入理解C指针之---结构体与指针

    一.结构体与指针 1.结构体的高级初始化.结构体的销毁.结构体池的应用 2.特征: 1).为了避免含有指针成员的结构体指针的初始化复杂操作,将所有初始化动作使用函数封装: 2).封装函数主要实现内存的 ...

  5. 深入了解Windows句柄到底是什么(句柄是逻辑指针,或者是指向结构体的指针,图文并茂,非常清楚)good

    总是有新入门的Windows程序员问我Windows的句柄到底是什么,我说你把它看做一种类似指针的标识就行了,但是显然这一答案不能让他们满意,然后我说去问问度娘吧,他们说不行网上的说法太多还难以理解. ...

  6. 关于C语言结构体,指针,声明的详细讲解。——Arvin

    关于结构体的详细分析 只定义结构体 struct Student { int age; char* name; char sex;//结构体成员 };//(不要忘记分号) Student是结构体的名字 ...

  7. c语言结构体&常指针和常量指针的区别

    结构体: 关系密切但数据类型不尽相同, 常指针和常量指针的区别: char * const cp : 定义一个指向字符的指针常数,即const指针,常指针. const char* p : 定义一个指 ...

  8. C#调用c++Dll 结构体数组指针的问题

    参考文章http://blog.csdn.net/jadeflute/article/details/5684687 但是这里面第一个方案我没有测试成功,第二个方案我感觉有点复杂. 然后自己写啦一个: ...

  9. Delphi结构体数组指针的问题

    //这段代码在Delphi 2007和delphi 7下是可以执行的,所以正确使用结构体数组和指针应该是这样的,已验证 unit Unit1; interface uses Windows, Mess ...

随机推荐

  1. redis-python

    一:缓存数据库介绍 NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库,随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特 ...

  2. python xlrd xlwt

    1.什么是xlrd模块? 2.为什么使用xlrd模块? 3.怎样使用xlrd模块? 1.什么是xlrd模块? ♦python操作excel主要用到xlrd和xlwt这两个库,即xlrd是读excel, ...

  3. Lintcode - 20.骰子求和

    题目: 扔 n 个骰子,向上面的数字之和为 S.给定 Given n,请列出所有可能的 S值及其相应的概率. 给定 n = 1,返回 [ [1, 0.17], [2, 0.17], [3, 0.17] ...

  4. mongodb插入数据获取本次插入的mongodb id

    最近接了一个别人的项目做二次开发,使用php进行mongodb的数据操作时,需要插入数据后得到相应的mongodb 中的id,简单代码如下 $data = array('test' => 'aa ...

  5. 基于C/S 结构的IM即时通讯软件--上篇

    目的:实现类似QQ群聊的聊天室,可以看到好友列表及互相传送信息. 分析:可基于C/S结构实现即时通讯 1.创建基于对话框的MFC程序(支持windows套接字),并增加相应的类与结构体,完善对话框界面 ...

  6. hadoop fs -text和hadoop fs -cat的区别(转)

    转自:https://www.jianshu.com/p/4462613d3f57

  7. 1、let const

    1.作用域的概念 es6之前 es5 分为 全局作用域 函数作用域 es6 新增块级作用域 2.let const 与 var 区别 用var 可以无报错 此代码报错 引出 块级作用域 用 {} 包起 ...

  8. 如何在Mac上用汇编语言写HelloWorld

    首先,Mac自带nasm,不过我们要先将其升级. 升级它的方法有很多种,因为我已经装好了homebrew,所以我直接在终端输入: brew install nasm 这样就升级啦- 接下来,创建一个H ...

  9. vue实例

    <!--需求: 背景图片,进度条,减和重置按钮 进度条填满红色,值为100%,点击减时,进度条依次减十,减到0时换一张背景图片,减按钮消失,点击重置按钮时,进度条重新填满红色-->效果图: ...

  10. Auzone AT60 TPMS Tool Update & Authorization Service: FREE

    This is a tutorial with step-of-step explanation of Auzone AT60 TPMS Tool Update & Authorization ...