四川省编导专业报考人数
VB真想不到之六:有用的技术和没用的指针
作者:AdamBear来源:CSDN
关键字:VB、SafeArray、数值类型指针
难度:中级
参考文章:
1、2000年7月VBPJBlackBelt专栏文章《ModifyaVarialbe'sPointer》
作者:BillMcCarthy
引言:
这真的是指针专题的最后一篇了(当然以后肯定还会提到指针)。主要是来谈谈BillMcCarthy的文章《ModifyaVarialbe'sPointer》的精华。关于这篇文章的东西,在我的《VB指针葵花宝典之SafeArray》里曾谈到过,但那篇文章实际上没有写出SafeArray的精华,用SafeArray最妙的地方在于可以将一个变量建在指定的内存处,就象上一篇文章给出的那个字串类一样。
正文:
BillMcCarthy在那篇《ModifyaVarialbe'sPointer》里用SafeArray实现多进程的数组共享内存,他考虑了数组变量的类型,因此可以兼容大部分数值类型的数组,是一个非常不错的东西。我这里不讲它实现的具体方法,只是想和大家一起看看SafeArray还能做什么。
修改SafeArray结构的pvData指针却是一个非常有用的技术,通过修改pvData,就能够通过数组直接访问指定的内存。
和上一篇文章包装字串指针类一样,通过修改pvData,我们也可以包装一些普通数值类型变量的指针类。
我在指针的第一篇文章里说过,要想实现C语言里'*'这个取指针所指变量值功能,必须要用CopyMemory。实际上我说错了,我们完全可以实现和C里一样的指针,如下:
//C语言
LongL;
Long*pL=&L;
*pL=12;
printf(L=%d*pL=%d,l,*pl);
'VB里
DimpLAsNewpLong,LAsLong
pL.AttachL
'也可以pL.Ptr=VarPtr(L)
pL=12
Debug.PrintL=;L;*pL=;pL
结果都能够通过修改pL指针,达到修改变量L的目的。
上面VB代码里的pLong就是一个包装好的Long型变量的指针类,下面看看如何来实现它:
OptionExplicit
'********************************************************
'pLong.cls
'包装一个Long型指针的类
'作者:熊超ID:AdamBear2002年3月18日
'http://www.csdn.net/Author/AdamBear
'你可以自由使用本类模块,不过请保留本声明
'********************************************************
PrivateDeclareSubCopyMemoryLibkernel32AliasRtlMoveMemory(DestinationAsAny,SourceAsAny,ByValLengthAsLong)
Privatem_Arr(0)AsLong
'缺省属性
PublicPropertyGetData()AsLong
Data=m_Arr(0)
EndProperty
PublicPropertyLetData(ByValValueAsLong)
m_Arr(0)=Value
EndProperty
PublicSubAttach(TargetAsLong)
Ptr=VarPtr(Target)
EndSub
PublicPropertyLetPtr(ByValTargetAsLong)
DimpSAAsLong
'得到SafeArray结构指针pSA
CopyMemorypSA,ByValVarPtrArray(m_Arr),4
'这个指针偏移12个字节后就是pvData指针
CopyMemoryByVal(pSA+12),Target,4
EndProperty
PublicPropertyGetPtr()AsLong
Ptr=m_SA.pvData
EndProperty
PrivateSubClass_Terminate()
CopyMemoryByValVarPtrArray(m_Arr),0&,4
EndSub
要将它改成Byte的指针类,只需要将上面的代码中m_Arr数组的类型,Data属性和Attach方法中的参数类型改为Byte型即可。
当我们这样做出pLong、pByte、pInteger后,我们就能够玩点和C里一样的花样了。
SubMain()
DimpBAsNewpByte,BAsByte
DimpIAsNewpInteger,IAsInteger
DimpLAsNewpLong,LAsLong
'用Attach方法将经过类型检查,直接用Ptr属性则可以绕过类型检查
pB.AttachB
pI.AttachI
pL.AttachL
'试试指针
B=1
Debug.PrintB=;B;*pB=;pB
pB=1
Debug.PrintB=;B;*pB=;pB
I=1000
Debug.PrintI=;I;*pI=;pI
pI=2000
Debug.PrintI=;I;*pI=;pI
L=40000
Debug.PrintL=;L;*pL=;pL
pL=60000
Debug.PrintL=;L;*pL=;pL
'试试C里的类型转换
'用Integer指针访问Long型变量
pI.Ptr=VarPtr(L)
Debug.Print*pI=;pI
EndSub
搞出这几种普通数值类型的指针类有什么用?基本上没有什么大用。不过是证明一种方法的可行性,和演示技术。这种技术还有什么用,需要的时候还会再谈。
后记:
本文的东西可见CSDN共享软件上的《内存共享和指针》,
指针的专题就到这儿了,下一篇准备开始着手写VB和COM的一个系列文章,其间我准备翻译一下《VBDesignPatterns》,这是一本不错的书。
9:43添加评论固定链接引用通告(0)记录它VisualBASIC
固定链接http://vercetti706.spaces.live.com/blog/cns!A467CB278DD3361A!200.entry
添加评论VB真想不到系列五
VB真想不到之五:高效字串指针类
作者:AdamBear来源:CSDN
关键字:VB、HCAK、字串指针、BSTR、效率、内存共享
难度:中级或高级
参考文章:
1、2000年7月VBPJBlackBelt专栏文章《ModifyaVarialbe'sPointer》
作者:BillMcCarthy
2、1998年4月VBPJBlackBelt专栏文章《PlayVB'sStrings》
作者:FrancescoBalena
引言:
本想以内存共享做为VB指针专题的最后一篇,写着写着发现字串的问题应该单独谈谈。在内存共享的问题上,我尤其关心的是字串的共享,因为在我一个多月前发布的源码里用的是《HardCoreVB》里BruceMckinney提供的CShareStr类,它实现了字串的内存共享。但是Bruce也没有突破局限,对字串的处理依然是CopyMemory的乾坤大挪移,尤其是还要进行讨厌的ANSI/DBCS和Unicode的转换。我在readme里说过它效率极低,应该采用Variant或Byte数组来实现,才能避免转换。后来又想到可以用StrPtr来做,并在VC里用DLL共享节实现了可以不进行转换的字串内存共享。不过在VC里我仍然需要用SysAllocString来建立VB能使用的BSTR。这都不是我想要的,我想要的东西要象VC里的CString的一样,只要字串够大,对其赋值就不用重新分配内存,还要象VC里CComBSTR类一样可以Attach到一个特定BSTR。
知道该怎么做,是在看了VBPJ上BillMcCarthy和FrancescoBalena的两篇文章之后。Bill用修改SafeArray描述结构实现了数组的内存共享,而Francesco则对字串指针进行深入的探讨。但是Bill和Francesco的东西都没有实现我想要的字串类。
方法知道了实现并不难,所以我决定自己来包装一个这样的东西。
正文:
使用VB里的字串类型String有两大不足:第一、它的分配是由VB运行时控制,我们不能将其分配在指定内存处;第二,任何一次对字串的赋值操作都要进行内存重新分配。要实现高效、灵活的字串处理,我们必须克服这两大不足。
对于第一个问题,通过修改String变量里放着的BSTR描述符指针可以实现;对于第二个问题,可以用Mid语句(注意是语句而不是函数)来赋值。不详细讲了直接看下面的这个类:
OptionExplicit
'********************************************************
'clsBSTR.cls
'作者:熊超ID:AdamBear2002年3月18日
'http://www.csdn.net/Author/AdamBear
'你可以自由使用本类模块,不过请保留本声明
'********************************************************
PrivateDeclareSubCopyMemoryLibkernel32AliasRtlMoveMemory(DestinationAsAny,SourceAsAny,ByValLengthAsLong)
'不要直接对sString赋值(可以用MID语句),将其设为公有仅为提高效率。
PublicsStringAsString'BSTR描述符指针
PrivatepStrAsLong'BSTR地址
PrivatenMaxLenAsLong'BSTR最大字节数
'让本字串指向特定地址
PublicSubAttach(AddrAsLong,OptionalnLenAsLong)
pStr=Addr
'修改BSTR描述符指针,使其指向Addr
CopyMemoryByValVarPtr(sString),Addr,4
IfIsMissing(nLen)ThenExitSub
'设定最大字串字节数
nMaxLen=nLen
EndSub
'还原本字串原BSTR描述符
PublicSubDetach()
CopyMemoryByValVarPtr(sString),0&,4
EndSub
'让本字串指向源字串
PublicSubAttachStr(sStrAsString)
AttachStrPtr(sStr),LenB(sStr)
EndSub
'data为缺省属性
PublicPropertyLetdata(sValAsString)
DimcAsLong
c=LenB(sVal)
'超过最大字串数,抛出错误。
Ifc>nMaxLenThenErr.RaisevbObjectError+3000,_
CString::LetData,溢出
'写字串长度
CopyMemoryByVal(pStr-4),c,4
'写字串
Mid(sString,1)=sVal
EndProperty
'可以通过公有变量sString来读字串,效率更高
PublicPropertyGetdata()AsString
data=sString
EndProperty
PrivateSubClass_Terminate()
CallDetach
EndSub
用法如下假设我们已通过VitualAlloc,HeapAlloc,MapViewOfFile这样的内存管理API得到了一个4k个字节的可读写的内存地址baseAddr:
DimsShareAsNewclsBSTR
'留下前4个字节用于BSTR保存字串字节数
sShare.Attach(baseAddr+4,4096-4)
'下面的字串Test会直接写到baseAddr+4字节处
sShare=Test
DimyAsString
'读字串时可以用sString属性或缺省属性
y=sShare.sString
'用AttachStr方法Attach到一个字串。
'必须要先Detach
sShare.Detach
sShare.AttachStr(y)
sShare=Hahaha
Debug.Printy
'一旦AttachStr到字串y后,对sShare的修改就相当于对y的修改。
'并且以后对y的修改也只能用Mid语句
Mid(y,1)=xxxxx
'不能直接赋值,这样VB会将原来y所指(也是sShare所指)内存释放,
'重新分配y。这样在访问sShare时会出错。
'y=Test
我也不在这里讲这个类的详细原理,可以参考我前面说的两篇文章。
使用这个类有几个需要注意的地方。
1、读字串时可以用sString属性来读,更快。
读sShare有两种方法,一种是用缺省属性Data来读,一种是直接用sString属性来读。用sString属性不重新分配内存,要快得多。
2、不要直接给sString赋值,应使用缺省的data属性来赋值。
之所以把sString属性暴露出来,是为了效率和方便。我们可以用Mid语句对其进行修改,但不要直接用=来赋值。
3、注意Attach的第二个参数,表示字串的最大字节数,不要让它超过已经分配的内存。
4、用AttachStr将本字串对象Attach到某个字串(比如上面的y)上后,不能再对这个字串y重新赋值,也不能将其传递到会对其重新赋值的过程。
哇,这么多需要注意的问题,用起来岂不是更不方便。的确用它的之前要考虑是不是必须的。因为建立这个类也一样有开销。所以还有一个需要注意的问题:
5、它主要的应用还是在于将字串安放在指定内存处。虽然它也可以让同一个进程内几个的字串达到共享的目的,但是如果只是两三个很小的字串这样时做反而慢了。
后计:
数组指针和字串指针我们已经谈过了,对于普通的数值类型变量的指针没有什么Hack的必要,但是它关系到一个有用的技术,下篇文章再谈。
本文和下篇文章的代码,以及用这个类来实现的共享内存的代码,我会发布到CSDN共享软件上,名字是《内存共享和指针》。
9:38添加评论固定链接引用通告(0)记录它VisualBASIC
固定链接http://vercetti706.spaces.live.com/blog/cns!A467CB278DD3361A!199.entry
添加评论VB真想不到系列四
VB真是想不到系列之四:VB指针葵花宝典之SafeArray
作者:AdamBear来源:CSDN
免责声明:本站发布的教育资讯(图片、视频和文字)以本站原创、转载和分享为主,文章观点不代表本网站立场。
如果本文侵犯了您的权益,请联系底部站长邮箱进行举报反馈,一经查实,我们将在第一时间处理,感谢您对本站的关注!
新励学网教育平台
海量全面 · 详细解读 · 快捷可靠
累积科普文章数:18,862,126篇