Yes, this topic is especially frustrating to a VB6 user. (ByRef means ByRef for ALL variable types! Strings, doubles, arrays, structures,etc.)
So, thanks to srod and demivec and jamba and others for finally drilling it into my thick skull.
It finally clicked with srod's "Dim A$(0)". This string element reallocates on the fly in the ByRef structured pointer case. Unlike a simple string variable, which causes all sorts of trouble if written beyond its original extents. So, my question for the PB-Team, is why can't simple string variables behave the same as 1-dimensional arrays of 1 element "behind the scenes". Emphasis on the Basic in PureBasic.
All bluster aside, I scanned through many thousands of lines of my code and there are actually only a few procedures that are manipulating strings in a ByRef fashion.
So much easier to design them out than to jump through the many hoops required here.
1. Use PeekS(*txt) / PokeS(*txt, "change to") inside Procedure(*txt)
Seems the simplest choice, as long as you do NOT write larger strings into unknown memory.
2. Use Global string variables
Works, but not my preference. Can get hard to keep track of status of variable.
3. Define string variables as Structures(S.string\s = "s") or 1 dimensional String array elements(dim S.s(0)) for later referencing inside procedures.
This works, but not elegant and lots to type.
Code: Select all
EnableExplicit
Define.s S
Define S2.String
Structure ST
x.i
s.s
y.i
EndStructure
Global ST.ST
Procedure ByRef4StrVar(*txt) ; Pointer to string variable
; Use this method for String variables and
; structures containing string variables.
; Clips string to original length
Protected.i inStrLen = MemoryStringLength(*txt)
Protected.s S
S = "Changed --> " + PeekS(*txt)
If Len(S) > inStrLen
PokeS(*txt, Left(S,inStrLen-1) + "~") ; truncated value
Else
PokeS(*txt, S, inStrLen)
EndIf
EndProcedure
Procedure ByRef4StrArr(*ptr.String)
; Use this method to dynamically change String Array elements
*ptr\s= "A" + Space(128) + "Z"
*ptr\s = ReplaceString(*ptr\s, " ", "~")
EndProcedure
Procedure NestedByRef(*txt)
ByRef4StrVar(*txt)
EndProcedure
Debug "Using ByRef4StrVar:"
S = "S"
Debug "S Before --> " + S
ByRef4StrVar(@S)
Debug "S After --> " + S
Debug "S After --> " + S
Debug "S After --> " + S
Debug ""
Debug "Using ByRef4StrVar:"
st\s = "err"
Debug "ST\S Before --> " + st\s
ByRef4StrVar(@st\s)
Debug "ST\S After --> " + st\s
Debug ""
Debug "Using ByRef4StrArr:"
S2\s = "S2"
Debug "S2\s Before --> " + S2\s
ByRef4StrArr(@S2)
Debug "S2\s After --> " + S2\s
Debug ""
Debug "Using ByRef4StrArr:"
Dim a$(0)
a$(0) = "A"
Debug "A$(0) Before --> " + A$(0)
ByRef4StrArr(@a$())
Debug "A$(0) After --> " + A$(0)
Debug Len(a$(0))
Debug ""
Debug "Using Nested ByRef:"
S = "S"
Debug "S Before --> " + S
NestedByRef(@S)
S = "SS"
NestedByRef(@S)
Debug "S After --> " + S