转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> VB.NET程序 >> 正文
VB真是想不到系列之四:VB指针葵花宝典之SafeArray         ★★★★

VB真是想不到系列之四:VB指针葵花宝典之SafeArray

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1635 更新时间:2009/4/23 16:39:30
mp1 = lStrPtrs(0, 3) : lTemp2 = lStrPtrs(1, 3)
     lStrPtrs(0, 3) = lStrPtrs(0, 0) : lStrPtrs(1, 3) = lStrPtrs(1, 0)
     lStrPtrs(0, 0) = lTemp1 : lStrPtrs(1, 0) = lTemp2
     当我们排好序后,我们还要将这个lStrPtrs里的指针元素写回去,如下:
     For i = Lo To Hi
        CopyMemory(ByVal VarPtr(MyArr(i)), lStrPtrs(0,i), 4) 
     Next  
     我已经不想再把这个方法讲下去,虽然它肯定可行,并且也肯定比用CopyMemory来移动数据要快,因为我们实际上移动的仅仅是Long型的指针元素。但我心里已经知道下面有更好更直接的方法,这种转弯抹角的曲线救国实在不值得浪费文字。

 
    四、HACK数组的BSTR结构,实时处理指针。
    最精采的来了,实时处理指针动态交换数据,好一个响亮的说法。
    我们看到,上一节中所述方法的不足在于我们的Long型指针数组里的指针是独立的,它没有和字串数组里的字串指针联系在一起,要是能联系在一起,我们就能在交换Long型指针的同时,实时地交换字串元素。
    这可能吗?
    当然,否则我花那么笔墨去写SafeArray干什么!
    在上一节,我们的目的是要把字串数组里的BSTR指针数组拿出来放到一个Long型数组里,而在这一节我们的目的是要让我们Long型指针数组就是字串数组里的BSTR指针数组。拿出来再放回去的方法,我们在上一节看到了,现在我们来看看,不拿出来而直接用的方法。
    这个方法还是要从字串数组的SafeArray结构来分析,我们已经知道SafeArray结构里的pvData指向的就是一个放实际数据的真数组,而一个字串数组如MyArr它的pvData指向的是一个包含BSTR指针的真数组。现在让我们想想,如果我们将一个Long型数组lStrPtrs的pvData弄得和字串数组MyArr的pvData一样时会怎样?BSTR指针数组就可以通过Long型数组来访问了,先看如何用代码来实现这一点:
    ''''模块级变量
    Private MyArr() As String  ''''要排序的字串数组
    Private lStrPtrs() As Long ''''上面数组的字串指针数组,后面会凭空构造它
    Private pSA As Long        ''''保存lStrPtrs数组的SafeArray结构指针
    Private pvDataOld As Long  ''''保存lStrPtrs数组的SafeArray结构的原
                               ''''    pvData指针,以便恢复lStrPtrs

  
    ''''功能: 将Long型数组lStrPtrs的pvData设成字串数组MyArr的pvData
    ''''    以使Long指针数组的变更能实时反应到字串数组里
    Private Sub SetupStrPtrs()
        Dim pvData As Long
       
        '''' 初始化lStrPtrs,不需要将数组设得和MyArr一样大
        ''''     我们会在后面构造它
        ReDim lStrPtrs(0) As Long
       
       ''''得到字串数组的pvData
        pvData = VarPtr(MyArr(0))

       ''''得到lStrPtrs数组的SafeArray结构指针
        CopyMemory pSA, ByVal VarPtrArray(lStrPtrs), 4
       
        ''''这个指针偏移12个字节后就是pvData指针,将这个指针保存到pvDataOld
        ''''    以便最后还原lStrPtrs,此处也可以用:
        ''''        pvDataOld = VarPtr(lStrPtrs(0))
        CopyMemory pvDataOld, ByVal pSA + 12, 4
       
        ''''将MyArr的pvData写到lStrPtrs的pvData里去
        CopyMemory ByVal pSA + 12, pvData, 4
       
        ''''完整构造SafeArray必须要构造它的rgsabound(0).cElements
        CopyMemory ByVal pSA + 16, UBound(MyArr) - LBound(MyArr) + 1, 4
        ''''还有rgsabound(0).lLbound
        CopyMemory ByVal pSA + 20, LBound(MyArr), 4
    End Sub
    看不懂,请结合图一再看看,应该可以看出我们是凭空构造了一个lStrPtrs,使它几乎和MyArr一模一样,唯一的不同就是它们的类型不同。MyArr字串数组里的fFeatures包含FADF_BSTR,而lStrPtrs的fFeatures包含FADF_HAVEVARTYPE,并且它的VARTYPE是VT_I4。不用关心这儿,我们只要知道lStrPtrs和MyArr它们指向同一个真数组,管他是BSTR还是VT_I4,我们把真数组里的元素当成指针来使就行了。
    注意,由于lStrPtrs是我们经过了我们很大的改造,所以当程序结束前,我们应该将它还原,以便于VB来释放资源。是的,不释放也不一定会引起问题,因为程序运行结束后,操作系统的确是会回收我们在堆栈里分配了却没有释放的lStrPtrs原来的野指针pvOldData,但当你在IDE中运行时,你有60%的机会让VB的IDE死掉。我们是想帮VB做点家务事,而不是想给VB添乱子,所以请记住在做完菜后,一定要把厨房打扫干净,东西该还原的一定要还原。下面看看怎么样来还原:   
    ''''还原我们做过手脚的lStrPtr
    Private Sub CleanUpStrPtrs()
        ''''lStrPtr的原来声明为:ReDim lStrPtrs(0) As Long
        ''''    按声明的要求还原它
        CopyMemory pSA, ByVal VarPtrArray(lStrPtrs), 4
        CopyMemory ByVal pSA + 12, pvDataOld, 4
        CopyMemory ByVal pSA + 16, 1, 4
        CopyMemory ByVal pSA + 20, 0, 4
    End Sub
   
    好了,精华已经讲完了,如果你还有点想不通,看看下面的实验:
    ''''实验
    Sub Main()
        ''''初始化字串数组
        Call InitArray(6)
       
        ''''改造lStrPtrs
        Call SetupStrPtrs
       
        ''''下面说明两个指针是一样的
        Debug.Print lStrPtrs(3)
        Debug.Print StrPtr(MyArr(3))
        Debug.Print
        ''''先看看原来的字串
        Debug.Print MyArr(0)
        Debug.Print MyArr(3)
        Debug.Print
       
        ''''现在来交换第0个和第3个字串
        Dim lTmp As Long
        lTmp = lStrPtrs(3)
        lStrPtrs(3) = lStrPtrs(0)
        lStrPtrs(0) = lTmp
       
        ''''再来看看我们的字串,是不是觉得很神奇
        Debug.Print MyArr(0)
        Debug.Print MyArr(3)
        Debug.Print
       
        ''''还原
        Call CleanUpStrPtrs
    End Sub
    在我的机器上,运行结果如下:
1887420
1887420

OPIIU
WCYKOTC

WCYKOTC
OPIIU
    怎么样?如愿已偿!字串通过交换Long型数被实时交换了。
    通过这种方式来实现字串数组排序就非常快了,其效率上的提高是惊人的,对冒泡排序这样交换字串次数很多的排序方式,其平均性能能提高一倍以上(要看我们字串平均长度,),对快速排序这样交换次数较少的方法也能有不少性能上的提高,用这种技术实现的快速排序,可以看看本文的配套代码中的QSortPointers。
    本道菜最关键的技术已经讲了,至于怎么做完这道菜,怎么把这道菜做得更好,还需要大家自己来实践。
   
    四、我们学到了什么。
    仅就SafeArray来说,你可能已经发现我根本就没有直接去用我定义了的SAFEARRAY结构,我也没有展开讲它,实际上对SafeArray我们还可以做很多工作,还有很多巧妙的应用。还有需要注意的,VarPtrArray不能用来返回字串数组和Variant数组的SafeArray结构的指针的指针,为什么会这样和怎样来解决这个问题?这些都需要我们了解BSTR,了解VARIANT,了解VARTYPE,这些也只是COM的冰山一角,要学好VB,乃至整个软件开发技术,COM还有很多很多东西需要学习,我也还在学,在我开始COM的专题之前,大家也应该自学一下。
    COM的东西先放一放,下一篇文章,应朋友的要求,我准备来写写内存共享。

后记:
    又花了整整一天的时间,希望写的东西有价值,觉得有用就来叫个好吧!

AdamBear
熊超
xcbear@netease.com

上一页  [1] [2] 


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台