Clarified the confusion of string parameters when VB calls APIs

Source: Internet
Author: User

Disclaimer: Part of this article comes from the network!

First of all, I think it is necessary to spend the effort on studying all kinds of tricky API strings called by VB. Based on the principles of rigor, problem discovery, and problem resolution, and in order to better understand the nature of the problem, I wrote a lengthy discussion. There are a lot of discussions about this on the Internet, but it is messy and hard to understand. Here is a summary! Let everyone have a clear understanding.

My problem starts with the difference between the byval varptr + variable and the directly written variable when the memory API is called. For example, there is no difference between byval varptr X and X. This is incorrect! Whether there are any differences between the two depends on the type of variable X. If it is a string, the two are completely different meanings; if it is any type other than the string type (and does not include the variant type), the two meanings are the same! Why? You will understand it.

First, let's talk about the string Storage Structure in VB. The string used in VB is BSTR in the COM specification, which is characterized by a four-byte prefix before the buffer to describe the length of the buffer:

In VB, the string type variable is not actually a string type, but a long type variable, it stores the pointer pointing to the string buffer (that is, the starting address pointing to the blue part in the figure ). The focus is on knowing the structure of the VB string. All the strings in VB are represented by Unicode encoding, while the strings in API are represented by asni. So when calling the API involves string parameters, the VB mom automatically helpsProgramThe member completes the conversion from Unicode to asni. That is to say, if you write an API, as long as the VB mom sees that there is a string in this API parameter, it will automatically help you create a temporary variable in the memory before passing the parameter, it is used to store the Conversion Result From Unicode to asni. All operations on the string are performed on this temporary variable. At this time, your original variable will be closed until the processing is complete, the careful VB mother gave the temporary variable value to the original string variable. This is the problem! This conversion process makes byval varptr x a world different from X! (Read multiple times if you cannot see it for the first time)

 

Let's look at an example:

Sub swapptr (SA as string, Sb as string)

Dim ltmp as long

Copymemory ltmp, SA, 4

Copymemory SA, Sb, 4

Copymemory Sb, ltmp, 4

End sub

Sub swapptr (SA as string, Sb as string)

Dim ltmp as long

Copymemory ltmp, byval varptr (SA), 4

Copymemory byval varptr (SA), byval varptr (SB), 4

Copymemory byval varptr (SB), ltmp, 4

End sub

 

This is a function for exchanging two strings. The first is incorrect, and the second is correct. The difference between the two functions is that there is no byval varptr.CodeIt is the same, but it turns out to be different!

 

Let's analyze the two codes. From a macro perspective, the two pieces of code are to retrieve the pointer to the buffer zone in the variable and then exchange it. Therefore, a long variable ltmp is defined to temporarily store the pointer. However, only the second part of the code is successful. First, why not? According to the general understanding: VB Mom first found that SA is a string parameter, and UA conversion is performed first. After the conversion is complete, the address is transmitted to the address of the copymemory temporary variable in the way of passing the address. After successful addressing, the asni string buffer pointer in the temporary variable is obtained, then give the 32-bit long pointer to ltmp. It seems that with this pointer, you can't find the real string. But do not ignore one problem: This is a temporary variable! Temporary buffer! When the copymemory ltmp, SA, and 4 statements are completed, the buffer will no longer exist! for copymemory SA, Sb, and 4, according to the above analysis, both SA and Sb are string type and all are converted, there are temporary variables. These two temporary variables are passed into your own address. copymemory finds the content in the address, that is, the buffer pointer. SB successfully handed over to SA's own cache pointer, after completion, the VB mother finds the corresponding string and converts it to Unicode and assigns it to sa Based on the pointer of the temporary variable. Now Sb is assigned to sa. However, when copymemory Sb, ltmp, and 4 are entered, sa cannot be given to sb, because the cache zone corresponding to ltmp has been released! Therefore, no value is obtained. Therefore, this code completes only half of the tasks. If you read this, you can understand it. If you are smart, you will immediately think of how to change the first code, a small change, so that the first code can be correct! The ltmp is changed to the sring type! let ltmp not store the buffer address of a temporary string variable, but store a real string! the biggest difference between the ltmp string type and the long type is that if the long type is used, only a temporary pointer is stored. If the string type is used, after the copymemory is executed, VB Mom will give the string corresponding to this temporary pointer to ltmp and put it in the buffer zone of ltmp. The second section of the Code uses byval varptr, so the VB mother does not perform UA conversion, there is no temporary variable, and the actual variable address is directly transmitted.

The following is a table for your understanding (this table comes from the network, and the variable name is inconsistent with this article, but the meaning is consistent !)

 

If you really understand what I said. If your mind is flexible enough. You will continue to think, and you will also be guided by the seventh sense: Do you need to clarify something?

I don't know how to think about it. Anyway, I realized that the first piece of code actually exchanges the buffer string (the buffer pointer in the variable SA and SB has not changed ), the second part of the code exchanges the pointer of the buffer in the SA and SB variables. Both of them achieve the purpose of exchange, but the results are completely different!

To verify this, you also need to clarify a problem:When a string variable in VB is defined, there is no buffer before the value is assigned, that is, before the memory space is allocated! That is, the buffer pointer is not stored in the string variable before the size is determined!

Sub swapptr (SA as string, Sb as string)

Dim ltmp as string

Dim lngbefore as long

Dim lngafter as long

Lngbefore = strptr (ltmp)

Copymemory ltmp, SA, 4

Copymemory SA, Sb, 4

Copymemory Sb, ltmp, 4

Lngafter = strptr (ltmp)

Msgbox lngbefore & "|" & lngafter

End sub

Call this code and you will find that the value of lngbefore is 0.

Sub swapptr (SA as string, Sb as string)

Dim ltmp as string

Dim lngbefore as long

Dim lngafter as long

Copymemory ltmp, SA, 4

Lngbefore = strptr (ltmp)

Copymemory SA, Sb, 4

Copymemory Sb, ltmp, 4

Lngafter = strptr (ltmp)

Msgbox lngbefore & "|" & lngafter

End sub

Call this operation to change the location of lngbefore = strptr (ltmp. This time, lngbefore is not 0. The two examples illustrate the above results and illustrate another problem:If there is a string parameter when calling the API, if it is not initialized, VB will automatically initialize it! But the API cannot know its size, and Initialization is not completed by the API, so there is a risk of memory access protection! (Insufficient length !), So try to initialize the string parameter before calling!

In addition, it is obvious that,In a string variable from initialization to release, its buffer remains unchanged!Lngbefore is always lngafter.

With the above foundation, we can use two pieces of code for verification: "In fact, the first piece of code exchanges the buffer string (the pointer to the buffer in the SA and SB variables has not changed ), the second code exchanges the pointer to the buffer zone in the SA and SB variables"

 

The first verification code:

 

Option explicit

Private declare sub copymemory lib "Kernel32" alias "rtlmovememory" (destination as any, source as any, byval length as long)

 

Private sub commandementclick ()

'Swapptr using pointers

Dim A as string

Dim B as string

Dim lngbeforea as long

Dim lngbeforeb as long

Dim lngaf.pdf as long

Dim lngafterb as long

 

A = ""

B = "B"

 

Lngbeforea = strptr ()

Lngbeforeb = strptr (B)

 

Swapptr a, B

 

Lngaf133 = strptr ()

Lngafterb = strptr (B)

 

Msgbox "value of A:" & &". Value of B: "& B & CHR (10 )&_

"Pointer stored before a" & lngbeforea & "pointer stored after a" & lngaf133 & CHR (10 )&_

"Pointer stored before B" & lngbeforeb & "pointer stored after B" & lngafterb

End sub

Sub swapptr (SA as string, Sb as string)

Dim ltmp as string

Copymemory ltmp, SA, 4

Copymemory SA, Sb, 4

Copymemory Sb, ltmp, 4

End sub

 

Result

 

Analysis:The values of A and B have been exchanged, but the buffer pointer of A and B has not changed, indicating that a and B are the buffer Content of the exchange.

 

The second verification code:

Option explicit

Private declare sub copymemory lib "Kernel32" alias "rtlmovememory" (destination as any, source as any, byval length as long)

 

Private sub commandementclick ()

'Swapptr using pointers

Dim A as string

Dim B as string

Dim lngbeforea as long

Dim lngbeforeb as long

Dim lngaf.pdf as long

Dim lngafterb as long

 

A = ""

B = "B"

 

Lngbeforea = strptr ()

Lngbeforeb = strptr (B)

 

Swapptr a, B

 

Lngaf133 = strptr ()

Lngafterb = strptr (B)

 

Msgbox "value of A:" & &". Value of B: "& B & CHR (10 )&_

"Pointer stored before a" & lngbeforea & "pointer stored after a" & lngaf133 & CHR (10 )&_

"Pointer stored before B" & lngbeforeb & "pointer stored after B" & lngafterb

End sub

Sub swapptr (SA as string, Sb as string)

Dim ltmp as long

Copymemory ltmp, byval varptr (SA), 4

Copymemory byval varptr (SA), byval varptr (SB), 4

Copymemory byval varptr (SB), ltmp, 4

End sub

 

Result

 

Analysis:The result exchange of A and B, and the buffer pointers stored in string variables A and B are also exchanged, which indicates that the buffer pointers stored in the and B variables are exchanged, to achieve the effect of content exchange.

 

Okay, I wrote it all morning... Now, I am not very clear about what I said. But it is all about the key. You also need to work hard to read it several times and think more. Leave a message if you do not understand it! Comments are welcome!

 

ReferenceArticle: Http://www.m5home.com/bbs/thread-2362-1-1.html

Http://blog.csdn.net/slowgrace/archive/2009/09/14/4549926.aspx

Http://www.cnblogs.com/xw885/archive/2005/11/22/105264.html

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.