当前位置:新励学网 > 秒知问答 > 四川省编导专业报考人数

四川省编导专业报考人数

发表时间:2024-07-19 16:02:25 来源:网友投稿

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

免责声明:本站发布的教育资讯(图片、视频和文字)以本站原创、转载和分享为主,文章观点不代表本网站立场。

如果本文侵犯了您的权益,请联系底部站长邮箱进行举报反馈,一经查实,我们将在第一时间处理,感谢您对本站的关注!