新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Dot NET,C#,ASP,VB 』 → C# 和内存指针(转载) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 2398 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: C# 和内存指针(转载) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     admin 帅哥哟,离线,有人找我吗?
      
      
      
      威望:9
      头衔:W3China站长
      等级:计算机硕士学位(管理员)
      文章:5255
      积分:18406
      门派:W3CHINA.ORG
      注册:2003/10/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给admin发送一个短消息 把admin加入好友 查看admin的个人资料 搜索admin在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给admin  访问admin的主页 引用回复这个贴子 回复这个贴子 查看admin的博客楼主
    发贴心情 C# 和内存指针(转载)


    发信人: Nineteen (-_-#!), 信区: DotNET
    标  题: C# 和内存指针(转载)
    发信站: BBS 水木清华站 (Fri Dec  5 09:28:30 2003), 转信

    C# 和内存指针  
    其它位置:  
    Key: C#,point,IntPtr,Marshal,PtrToStructure,typeof. Author: ArLi @ http://www.zpcity.com/arli/
    虽然到了.net 的runtime 时代,C 仍然是不可磨灭的主要支柱,包括在MSDN 里见到的API 大部都是有指针类型存在,那么在以C 冠首的C# 里应当如何去使用指针呢?  
    其实,C# 里可以直接使用结构型的变量引用进API,但是毕竟它不是指针在对一些涉及以结构数组存放的内存区操作可能就力有不及了,我举一个例子要使用到结构数组的一个API(对这个API 不必加以了解,我们不是主说API):

    NET_API_STATUS NetShareEnum(
    LPWSTR servername,
    DWORD level,
    LPBYTE* bufptr,
    DWORD prefmaxlen,
    LPDWORD entriesread,
    LPDWORD totalentries,
    LPDWORD resume_handle
    );

    及它要用到的结构 (设 level 为1):

    typedef struct _SHARE_INFO_1 {
    LPWSTR shi1_netname;
    DWORD shi1_type;
    LPWSTR shi1_remark;
    } SHARE_INFO_1, *PSHARE_INFO_1, *LPSHARE_INFO_1;


    在第三个参数 LPBYTE* bufptr 它就是一个指针,而非C 型传统语言的数组的做法,就可以直接声明成 ref SHARE_INFO_1[] bufptr,但我不推荐这么做,原因之一在C# 似乎还不支持结构数组块,而且它并没有存在数组型结构参数的重载。暂且不说如何去实现它,我希望以 C 的操作方式-指针去实现,所以我转成 C# 声明如下:

    [StructLayout(LayoutKind.Sequential)]
    protected struct SHARE_INFO_1 {
    [MarshalAs(UnmanagedType.LPWStr)] public string shi1_netname;
    [MarshalAs(UnmanagedType.U4)] public uint shi1_type;
    [MarshalAs(UnmanagedType.LPWStr)] public string shi1_remark;
    }

    [DllImport("Netapi32.dll", EntryPoint="NetShareEnum")]
    protected static extern int NetShareEnum(
    [MarshalAs(UnmanagedType.LPWStr)] string servername,
    [MarshalAs(UnmanagedType.U4)] uint level,
    ref IntPtr bufptr,
    [MarshalAs(UnmanagedType.U4)] uint prefmaxlen,
    [MarshalAs(UnmanagedType.U4)] ref uint entriesread,
    [MarshalAs(UnmanagedType.U4)] ref uint totalentries,
    [MarshalAs(UnmanagedType.U4)] ref uint resume_handle
    );

    在上面的函数执行完成后,会在指针 bufptr 所指的位置存在一个数据块,此内存块的数据格式是以 SHARE_INFO_1 结构排列的(假设level为1),并且在 entriesread 中指示该块的结构个数,那么我们要如何将它转成真正可用的类型到 SHARE_INFO_1[] shareInfo; 变量中去呢,其实 C# 提供了一种 Marshal.PtrToStructure 的方法,它就是专门将指针所指的非托管内存块搬到托管内存中的指定的结构中去,可它不支持结构数组(目前.net 1.1 还没有该重载实现过),所以只好也最好一个一个的搬(而且一个一个搬更形象些),例子如下:

    Int32 ptr = bufptr.ToInt32();
    for (int i=0; i<entriesread; i++) {
    //开始将ptr 所指的内存块中搬一个SHARE_INFO_1 结构大小并按SHARE_INFO_1 格式排列的数据到 SHARE_INFO_1 型变量 shareInfo 中去
    SHARE_INFO_1 shareInfo = (SHARE_INFO_1)Marshal.PtrToStructure(new IntPtr(ptr), typeof(SHARE_INFO_1));  
    ptr += Marshal.SizeOf(shareInfo); // 这是将指针向后移一个结构位,因为已经移完一个结构了

    //TODO: 操作当前的 shareInfo
    }

    上面的例子很明显了,bufptr 就是指针,该例子就是将内存中的指针所指的内存块(非托管内存)以一个指定结构的大小和排列格式移动.net 内存(托管内存)中的一个变量去,然后将指针向后移一个位置(ptr += Marshal.SizeOf(shareInfo)),此位置由指针当前位置加上 Marshal.SizeOf(shareInfo) 也就是已经移完的大小获得,它的意思其实就是将指针移到已经搬完的数据的后面去准备搬一下结构块

    这个例子只是说明指针的用法,并不是主要说API 对该API 及它的参数不必细加研究
      
    2003.10.9  

    --
    ——长夜漫漫,无心睡眠……难道狼妹妹也睡不着吗?


    ※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.206.3.3]
    上一篇
    返回上一页
    回到目录
    回到页首
    下一篇


       收藏   分享  
    顶(0)
      




    ----------------------------------------------

    -----------------------------------------------

    第十二章第一节《用ROR创建面向资源的服务》
    第十二章第二节《用Restlet创建面向资源的服务》
    第三章《REST式服务有什么不同》
    InfoQ SOA首席编辑胡键评《RESTful Web Services中文版》
    [InfoQ文章]解答有关REST的十点疑惑

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/9 2:25:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/16 6:49:56

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    1,458.984ms