VB really can't think of the four four: VB pointer Sunflower Collection SafeArray

zhaozj2021-02-17  54

This series of articles visible: http://www.9cbs.net/develop/list_article.asp?author=adambear

VB really can't think of a series of four: VB pointer Sunflower Collection SafeArray Keywords: VB, HCAK, pointer, SafeArray, array pointer, efficiency, array, sorting difficulty: intermediate or advanced requirements: familiar with VB, understand basic sorting algorithms, VC is better.

Introduction: Up to back In C, we have used pointers to come, they have come to come, and they want to do whatever you want. In VB, in VB, we use pointers to seek your predecessor, even if a byte is used to use CopyMemory Qiankun Migrant, really tired. Today, let's take a look, can you let the pointer in the VB do you want to play, and learn the Lingbo of the VB pointer. Everyone looks at the official, you have a tea. I. Help VB Do something COM housework, this series opens the first one, I have said that the success of VB has been said to the COM development group, COM is a good brand of M $, from OLE To COM , COM is one of M $ most successful technology in the past decade, so it is necessary to blow a few words. The COM component object model is the foundation of VB, Varinat, String, Current, Date These data types are COM. We use the CXXX functions such as CSTR, CINT, CSNG. It is also written by the COM development group, and even we used in VB. Mathematical functions, there are corresponding VARXXXDIV, VARXXXADD, VARXXXABS in COM. Hey, the VB development team is very smart. We can also say that COM's success also has a VB development team and countless VB programmers, Bill Uncle Bunding COM and VB are bundled together. So, learn VB without a need to understand COM, you are happy, you enjoy VB to bring you a relaxed letter, she dredes those trivial housework, but you are unfortunate, because you have never been I didn't know the VB you love. If you have a temper for you, you don't even know how to comfort her. Therefore, this series will take a few major articles to teach you how to help VB do members of COM, in order to prepare. I want to learn all COM housework, it is not easy. Today, we will take an array to open a head, and more technologies I will come again later. Second, the SafeArray in COM automation is like a washing machine, the rice rice, the dust collector, VB washing clothes, cooking, and cleaning health will use COM automation. It contains everything in COM, all women can use COM automation to do housework, whether sharp vc, gentle VB, or small VBScript, they can use COM automation, and can also pass COM automation gossip Homemade, exchange of feelings. This is because COM automation provides a generic data structure and data conversion. The data structure of VB is basically a data structure of COM, such as arrays in VB, called SafeArray in COM. Therefore, when you process an array in VB, we must clearly know that we are in handling SafeArray, a secure array in COM. Prepare the kitchen to do a dish of the array pointer, see the real structure of SafeArray, let us know the array of C.

The pointer to the first element of the first element in C and C is a matter, such as the following: #include using namespace std; int main () {int a [10]; cout << "A = "<< a << endl; cout <<" & a [0] = "<< & a [0] << endl;} ///: ~ You can see the result A and & A [0] are the same, here The array is a true array in the data structure, and they are stored in memory, and we can access the subsequent elements through the first element, we can call such an array "true group." However, it is not safe, because we cannot know very important information such as dimension, elements of the elements, etc., which cannot be controlled from this real number of pointers, so access to this array cannot be controlled. We can do a two-dimensional array when C will have a one-dimensional number of groups, we can also access the memory outside the number of memory through an index of the array size, but these are extremely unsafe, array boundary errors can be said to be C A very easy to make mistakes that are not easy to find. Therefore, there is a SAFEARRAY security array in the COM to solve this problem. When we pass an array in VB, the Safearaay structure is as follows: Private TypeArray CDIMS AS INTEGER ' How many days is this array? What is the characteristic of the array of ffeatures as integer?? How big is the Cbelements as long 'array? CLOCKS AS Long 'This array is locked a few times? Where is the data in this array in PVDATA AS long? 'Rgsabound () AS SFARRAYBOUND End Type This RgSabound immediately after PVDATA is a true group, so you can't declare it in the above structure, remember, in VB in VB is SafeArray, no declaration in VB Method of true group. But this is not a problem, because the true group of the Sfarraybound structure is constant in the entire Safearray structure, always in the end, we can use a pointer to access it. The number of Elements of the SfaRayBound array has CDIMS, each element records an array dimension message, look at it looks like it: How many elements do this of the VIVATE SAFEARRAYBOUND CELEMENTS AS LONG '? LLBOUND As long 'its index starts from? End Type still has something that is not clear, that is, ffeatures in the SafeArray structure. It is a set of flags to indicate those surpapers. These features have no need to understand carefully. This article can't be used. I will explain again when I use them. I saw the things above, everyone must be very big, so I can't use so many things in this article. After reading this article, you will know that it is not difficult to understand.

Let's take a look at the following statement: DIM Myarr (1 to 8, 2 to 10) AS long This array is what SafeArray is in memory? FIG. A: cDims = 2 fFeatures = FADF_AUTO AND FADF_FIXEDSIZE position 0cbElements = 4 LenB (Long) 4cLocks = 08pvData (true point array) 12rgsabound (0) .cElements = 816rgsabound (0) .lLbound = 118rgsabound (1) .cElements = 922rgsabound (1) .llbound = 226

cDims = 2 fFeatures = FADF_AUTO AND FADF_FIXEDSIZE position 0cbElements = 4 LenB (Long) 4cLocks = 08pvData (true point array) 12rgsabound (0) .cElements = 816rgsabound (0) .lLbound = 118rgsabound (1) .cElements = 922rgsabound (1). Llbound = 2 26

Figure 1: SafeArray memory structure

CDIMS indicates that it is a 2-dimensional array. SFEATURES indicates an array of fixed-size assigned in the stack. Cbelements indicates that each element size is long, PVData points to the true array (that is, the C. Array), RgSabound This truth indicates the size of the two dimension of arrays and the index start position value of each dimension. Let's take a look at what we can do from this. For example, you have to get a plurality of dimensions. There is no way to provide this in VB. There is a variable method to capture the following: on Error Goto BoundSerror for i = 1 to 1000 'does not have such a multi-dimensional array ltemp = lbound (myarr, i) NextBounderro: ndims = i - 1 msgbox "" & ndims & "dimension"

Now we know the principle of SafeArray, so you can also get the dimension directly, as follows: 'First get a pointer to the pointer to the SafeArray structure, what is the principle, I will say it. PPMYARR = VARPTRARRAY (Myarr) 'From this pointer to get the pointer of the Safearray structure CopyMemory PMYARR, BYVAL PPMYARR, 4' Remove CDIMS CDIMS COPYMEMORY NDIMS, BYVAL PMYARR, 2 MSGBOX from the first two bytes of the address referred to in this pointer An array has "& NDIMS &" Dimension "

How is it, do you understand that lbound is actually the llbound of Rgsabound in SafeArray, and Ubound is actually equal to LLBound Celements - 1, now I will ask, what should IUBOUND be equal? DIM AEMPTYARRAY () As long iubound = Ubound (aemptyArray) The correct answer is -1, not surprising, llbound-c-c-c-c-c1 = 0 - 0 - 1 = -1 So check uBOUND is not equal to -1 is a judgment array is Good way to empty array. There is also a real number of SafeArray structures pointing to the actual data. It is actually a pointer to the first element of the real number group, that is, the following equation: pvdate = varptr (Myarr (0)) is on the previous In the article, we pass the address Varptr (xxxx (0)) of the first element of the array, which means that we are passing the truth, we can move directly on the real group, pass. But how do you get a pointer for an array SafeArray structure? You should pay attention to the Varptrarray used above, its declaration is as follows: Declare function varptrarray lib "msvbvm60.dll" _ alias "varptr" (var () as any) as long it is Varptr, only the parameter declaration is VB array, when it returns it is a pointer to a pointer to an array SafeArray structure. Because Varptr will return the address of the parameter passed to it, and by Byref is transmitted to it. As mentioned earlier, it is actually a pointer to a SafeArray structure, and Varptrarray will return the pointer of this pointer. So to access the SafeArray structure, as follows: Return PPSA with Varptrarray, then get the PSA to which it points to the PSA, PSA is pointed to the Safearray structure, and we have access to the SafeArray structure to use this PSA pointer. Now you should have learned about SafeArray, just like this, we can have Hack in VB.

Third, the HACK array character string pointer This is already the third story of the pointer, I always say how to let us do, but you don't think that in addition to how I have said, you have not I feel that it is used, in fact, this is because I am eager to ask for it. Before I talk about it, I will reason if I should use the pointer in the case. Only with pointer types! nonsense? I mean, like Integer, Long, Double type of numerical types such as integer, there are directly variables, and VB processes them not slow, there is no need for HACK. But strings, and Variant, including strings, arrays, objects, and structures, as well as arrays including strings, object structure they are pointers, and actual data is not placed in variables, and variables are pointed, because VB is not directly Support pointers, the operations must be made together with the data copy. Sometimes we don't want to assign a value, we just want to exchange their pointers, or want multiple pokes to point the same data, let multiple variables to the same memory operation, to achieve such purposes, do not hack in VB. This is especially true for arrays, such as what we have to do today: Sort a string array. We know that the sorting of the string array is used to exchange string elements. When assigns a value in VB, you must first release the original string, and then create a string, and copy the source string. Come, very time consuming. In the concept of COM, such as the operation of strings a, b, first use sysfreestring (a) to release the original string A, then use a = sysallocstring (b) to create new and copy strings, understand This will know that do not exchange the value when the string is switched, but it should be exchanged directly to exchange the string pointer. I introduced this way of exchange strings in the first article of the pointer, which can be great. Improve the speed of the exchange string. However, this exchange is at least two CopyMemory to write the pointer back, and the number of times the CopyMemory is called when switching multiple strings, and the efficiency has a lot loss. In fact, the pointer is only 32-bit integers, and two pointers are exchanged in C, only the three LONG type integers are required. So we have to think about we can put all the string pointers in the string array in a LONG type pointer, we only exchange the elements in this long-type group, which is equivalent to exchanged string pointers, row After a good order, rewrite this LONG type pointer array to all string pointers in the string array, and avoid multiple use of CopyMemory to exchange string pointers in two or two times. So all of our exchange operations are performed for a long-type array. To know the exchange of two long-type integers, it is as fast in VB and in C. Now our problem becomes how to take a string pointer in the string array in one time, and how to write back the adjusted string pointer. Without the SafeArray structure of a moving array, we can complete it with Strptr.

We know that the string array element is actually a string pointer, which is the BSTR pointer, putting these pointers in a long-type array, very simple, with the following method: private sub getstrptrs () DIM HI as long , LO As Long Hi = Ubound (Myarr) LO = LBOUND (Myarr) Redim Lstrptrs (0 to 1, LO TO HI) AS Long Dim I as Long for i = LO TO HI LSTRPTRS (0, I) = Strptr (Myarr i)) 'BSTR pointer array lstrptrs (1, i) = I' original number group index next End Sub Why use 2 dimensional arrays, this is the need for sorting, because when we exchange the LONG type pointer in LSTRPTRS, the original word The string pointer in the string array myarr is not simultaneously exchanged, so when the string is accessed with the LONG type pointer in lstrptrs, the original index must be recorded with 2 dimensional arrays simultaneously record each LONG type pointer. Index in the original string array. If you only use a 1-dimensional array, you will use CopyMemory if you access the string, such as accessing the string referred to by the third element of the LSTRPTRS, to use the following method: CopyMemory Byval Varptr (StrtemP), LSTRPTRS (3), 4 Although as long as we guarantee that strTemp is large enough, add some clean jobs, this approach is possible, but in fact, we also see that you still have to call CopyMemory multiple times, actually considering the original string array Myarr has been It has not changed, we can access the string by an index, the same function above is now: startemp = myarr (lstrptrs (1, 3)) 'is independently read from the original string number. However, when we exchange two long-type pointer elements in lstrptrs, we also remember to exchange their indexes, such as exchange of the 0th and 3 elements, as follows: ltemp1 = 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 After we are in the order, we have to write the pointer elements in this lstrptrs, as follows: for i = lo to hi copymemory (byval varptr (Myarr (i)), LSTRPTRS (0, i), 4) NEXT I have I don't want to tell this method, although it is sure, and it is definitely faster than moving data with CopyMemory, because we actually move only the long-type pointer element. But my heart already knows that there is a better and more direct way, this curve of this turning angle is not worthy of waste.

Fourth, the HACK array BSTR structure, real-time processing pointer. The most brilliant, real-time processing pointer dynamically exchange data, a loud statement. We see that the shortage of the method described in the previous section is that the pointer in our long-type pointer is independent. It does not contact the string pointer in the string array, if you can contact it, we will String elements can be exchanged in real time while switching the LONG type pointer. is it possible? Of course, otherwise I spend so ink to write SafeArray! In the previous section, our purpose is to take it out of the BSTR pointer array in the string array to a long-type array, and our purpose in this section is to let us Long type pointer array is a string array. BSTR pointer array. Take out and then put it back, we have seen it in the last section, now let's take a look, don't take it out and directly use. This method is to analyze from the SafeArray structure of the string array. We already know that the PVData in the SafeArray structure is a real number of actual data, and a string array is like Myarr's PVData points to a BSTR pointer. Real group. Now let us think about what happens if we make a LONG type LSTRPTRS pvdata make the string array myarr's PVData? The BSTR pointer array can be accessed through the long-type array, first look at how to use code: 'Modular variable private myarr () AS String' To sort the string array private lstrptrs () as long 'above String pointer array, after constructing its Private PSA as long 'SafeArray structure pointer private pvdataold as long' of the LSTRPTRS array Safearray's original 'PVDATA pointer to restore LSTRPTRS' Function: WONG Type LSTRPTRS PVDATA sets a string array Myarr's PVDATA 'to enable the change of the LONG pointer to react in real time to the string array private sub setupstrptrs () Dim Pvdata as long' initializes lstrptrs, do not need to make the array to myarr. We will construct it behind it Redim lstrptrs (0) as long 'to get a string array PVData PVDATA = Varptr (Myarr (0))

'Get the LSTRPTRS array SAFEARRAY structure pointer CopyMemory PSA, BYVAL VARPTRARRAY (LSTRPTRS), 4' This pointer offloads 12 bytes later is the PVDATA pointer, saving this pointer to PVDataLD 'to last restore LSTRPTRS, which can also be used here: 'Pvdatald = varptr (lstrptrs (0)) CopyMemory Pvdataold, Byval PSA 12, 4' Write myarr PVDATA to Pvdata in LSTRPTRS to CopyMemory Byval PSA 12, PVDATA, 4 'Complete Construction SafeArray must construct it RGSABound (0) .CELEMENTS COPYMEMORY BYVAL PSA 16, Ubound (Myarr) - LBound (Myarr) 1, 4 'has rgsabound (0) .llbound CopyMemory Byval PSA 20, LBound (Myarr), 4 End Sub can't understand Please see again and again, you should see that we have a lstrptrs that we are constructed, so that it is almost the same as Myarr, the only difference is that they have different types. The ffeatures in the Myarr string array contains Fadf_BSTR, while LSTRPTRS's ffeatures contains fadf_havevartype, and its VARTYPE is VT_i4. Don't care about it, we just need to know that lstrptrs and myarr points to the same real number, manage him is BSTR or vt_i4, we put the elements in the true group as a pointer to make it. Note that because lstrptrs are our great transformation, we should restore it before the program ends so that VB will release resources. Yes, don't release it, don't necessarily cause problems, because the program is running, the operating system does recover we allocate the original wild pointer PVOLDDATA that has not been released in the stack, but when you run in the IDE, You have 60% of the opportunity to let VB's IDE dead. We want to help VB to do something home, rather than want to add a chaos to VB, so remember that after doing food, be sure to clean the kitchen, and you must restore it.

Let's take a look at how to restore: 'Restore the LSTRPTR Private Sub CleanupstrPtr Private Sub CleanupStrptrs ()' lstrptr's LSTRPTRS (0) As long 'in the claim to restore it CopyMemory PSA, ByVal VarptraRray (LSTRPTRS) , 4 CopyMemory Byval PSA 12, Pvdatald, 4 CopyMemory Byval PSA 16, 1, 4 CopyMemory Byval PSA 20, 0, 4 end Sub is good, the essence has been finished, if you still don't want, look at the following Experiment: 'Experiment SUB Main ()' Initi-String Array CALL INITARRAY (6) 'Regenerated LstrPTRS CALL SetupstrPTRS' Next Description Two pointers are the same debug.print lstrptrs (3) Debug.print strptr (Myarr (3)) Debug .Print 'first look at the original string debug.print myarr (0) Debug.print myarr (3) debug.print' now exchange 0th and 3 string DIM LTMP AS long LTMP = LSTRPTRS (3) LSTRPTRS (3) = lstrptrs (0) lstrptrs (0) = ltmp 'Take a look at our strings, is it very mysterious debug.print myarr (0) Debug.print Myarr (3) debug.print' Restore CALL CleanupStrPTRS End Sub in mine On the machine, the results are as follows: 1887420 1887420OPIUWcykotc

How about Wcykotcopiu? Wish is repay! Strings are exchanged in real time by swapping the LONG model. In this way, the string array is quickly sorted very quickly. The improvement in efficiency is amazing, and the number of exchanging strings of bubbling is more sorted, and the average performance can be doubled (to see us The average length of the string, the method of rapid sorting, there is a small number of exchanges, and there is a lot of performance, using this technique to achieve rapid sorting, you can look at the QSortPointers in the supporting code of this article. The most critical technology of this Daofei has already talked. As for how to do this dish, how to do this dish better, you still need to practice yourself. Fourth, what we learned. Only for SafeArray, you may have discovered that I didn't directly use the SafeArray structure I defined. I didn't show it. In fact, we can do a lot of work for SafeArray, and a lot of clever applications. It is also important to note that Varptrarray cannot be used to return a pointer to the pointer of the string array and the Variant array of SafeArray structures, why do you solve this problem like this? These requires us to understand BSTR, learn from Variant, learn from Vartype, these are only COM's icebergs, you have to learn VB, and even the entire software development technology, COM still has a lot of things need to learn, I am still learning, I started COM. Before the topic, everyone should learn from school. COM's things first put a place, next article, should be friends, I am ready to write memory sharing. Postscript: I spent a whole day, I hope to write something value, I feel useful to call it!

Adambear Xiong Chao Xcbear@netese.com

转载请注明原文地址:https://www.9cbs.com/read-28392.html

New Post(0)