Passing string paramerter by reference to a procedure

Just starting out? Need help? Post your questions and find answers here.
RobertRioja
User
User
Posts: 88
Joined: Thu May 02, 2019 3:57 am
Location: USA
Contact:

Passing string paramerter by reference to a procedure

Post by RobertRioja »

How do I pass a string by reference to a procedure. In other words, how do I pass a pointer to a string so that the procedure can change the contents of the string?

I tried this but it did not work:

Code: Select all

Procedure.l GetErrorMessage(*AnErrorMessage.String)

  *AnErrorMessage\s = "This is the message"

EndProcedure


  S$ = " "
  *Pointer.String = @S$
  GetErrorMessage(*Pointer)
  debug *Pointer\s
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Passing string paramerter by reference to a procedure

Post by mk-soft »

You need a Pointer to the Pointer of String

define Text$ is only Pointer to the String

Code: Select all

Procedure.l GetErrorMessage(*AnErrorMessage.String)

  *AnErrorMessage\s = "This is the message"

EndProcedure


Define StringByRef.String

StringByRef\s = ""
  
GetErrorMessage(StringByRef)
Debug StringByRef\s

Structure udtText
  s.s
EndStructure

Define MyErrorText.udtText
GetErrorMessage(MyErrorText)
Debug MyErrorText\s


My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
RobertRioja
User
User
Posts: 88
Joined: Thu May 02, 2019 3:57 am
Location: USA
Contact:

Re: Passing string paramerter by reference to a procedure

Post by RobertRioja »

Thank you for your help. I got it to work. I was close... But you were closer.

Robert
User avatar
idle
Always Here
Always Here
Posts: 6214
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Passing string paramerter by reference to a procedure

Post by idle »

pb strings are stored in the datasection of your program which makes them a little funky
so you just need to allocate a buffer which is on the heap and it'll work as expected

Code: Select all

Procedure.i GetErrorMessage(*AnErrorMessage.string)
  
  *AnErrorMessage\s = "This is the message"
      
EndProcedure


Global *StrE.String = AllocateMemory(255*SizeOf(Character))
GetErrorMessage(*StrE)
Debug *StrE\s
FreeMemory(*strE) 
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Lord
Addict
Addict
Posts: 913
Joined: Tue May 26, 2009 2:11 pm

Re: Passing string paramerter by reference to a procedure

Post by Lord »

Why is Global for *StrE.String necessary as you provide the
adress by *StrE to the procedure?
It works without.
Image
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Passing string paramerter by reference to a procedure

Post by mk-soft »

@idle,

Your example is completely wrong and lead to the memory leak.

A pointer variable from Type String is a pointer on a pointer to the string.
After assigning a string, this then picks up the pointer to the string.

Code: Select all

Procedure.i GetErrorMessage(*AnErrorMessage.string)
  
  *AnErrorMessage\s = "This is the message"
      
EndProcedure

Debug "Size Of Type String: " + SizeOf(String)

Debug "Allocate Structure Of Type String"
Global *StrE.String = AllocateStructure(string)
Debug "Act Value of Pointer to String: " + PeekI(*StrE)
Debug "Call Function..."
GetErrorMessage(*StrE)
Debug "Act Value of Pointer to String: " + PeekI(*StrE)
Debug "PeekS String over Pointer: " + PeekS(PeekI(*StrE))
Debug "Default Output: " + *StrE\s

Debug "Free Structure: Is Freed String and Memory"
FreeStructure(*strE) 
My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Passing string paramerter by reference to a procedure

Post by mk-soft »

Small Trick

Update

Code: Select all


Macro GetVarPtr(_Var_, _Pointer_)
  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    lea rax, _Var_
    mov _Pointer_, rax
  CompilerElse
    lea eax, _Var_
    mov _Pointer_, eax
  CompilerEndIf  
  DisableASM
EndMacro

Procedure.i GetErrorMessage(*AnErrorMessage.string)
  
  *AnErrorMessage\s = "This is the message - " + *AnErrorMessage\s
      
EndProcedure

Define text.s, *pText

text = "Hello World"
GetVarPtr(text, *pText)
GetErrorMessage(*pText)
Debug text
My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: Passing string paramerter by reference to a procedure

Post by nco2k »

Code: Select all

Procedure.l GetErrorMessage(*AnErrorMessage)
  Protected *String.String = @*AnErrorMessage
  *String\s = "This is the message"
EndProcedure

S$ = " "
GetErrorMessage(@S$)
Debug S$
dunno if its safe to use though. i have no idea how pb's string builder deals with this internally.

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Passing string paramerter by reference to a procedure

Post by mk-soft »

@nco2k

that's wrong too.

You change the String at the Memory, not the Pointer to the String... Memory leak too.

Code: Select all

Procedure.l GetErrorMessage(*AnErrorMessage)
  Protected *String.String = @*AnErrorMessage
  *String\s = "This is the message" + *String\s
  Debug *String\s ; Bad String -> Memory leak
EndProcedure

S$ = "Test "
GetErrorMessage(@S$)
Debug S$
Right Methode like API

Code: Select all

; API Methode

Procedure.i GetErrorMessage(*AnErrorMessage, MaxLen)
  
  PokeS(*AnErrorMessage, Left("This is the message", MaxLen))
      
EndProcedure

text.s = Space(255)

GetErrorMessage(@text, Len(text))

Debug text

My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
User avatar
idle
Always Here
Always Here
Posts: 6214
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Passing string paramerter by reference to a procedure

Post by idle »

thanks wasn't thinking
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Piero
Addict
Addict
Posts: 1204
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Passing string paramerter by reference to a procedure

Post by Piero »

Thanks mk! (as always)

I hope this "reference code" I made (for me to remember some "pointer/memory strings stuff") makes some sense…

Code: Select all

#smax = 255
Define text.s = Space(#smax) ; "allocate"

Procedure s(*s,s.s)
   ; Shared text : text+Space(Len(s)) : *s=@text ; "redim" example
   Protected *ss=*s
   CopyMemoryString("Hello", @*ss) ; or e.g. (Left(s,#smax),@*ss), (Peeks(@protected_str$,#smax),@*ss)…
   CopyMemoryString(" World!")
   Debug PeekS(*s)
   PokeS(*s,s,#smax,#PB_String_NoZero) ; no need for *ss
   ; PokeS(*s,PeekS(@s,#smax),-1,#PB_String_NoZero)
EndProcedure

s(@text,"Pizza")
Debug text
text = #Null$ ; to really free a string
Mesa
Enthusiast
Enthusiast
Posts: 477
Joined: Fri Feb 24, 2012 10:19 am

Re: Passing string paramerter by reference to a procedure

Post by Mesa »

Without pointer:

Code: Select all

Procedure test(MyString.i) 
	Protected *s.string = @MySTRING
	
	*s\s="This is the message"
	Debug *s\s
	Debug PeekS(MySTRING)

EndProcedure



test$=""
test(@test$)
Debug test$ + " outside the procedure"
M.
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Passing string paramerter by reference to a procedure

Post by mk-soft »

This is completely wrong here. You transfer the pointer to the string and not the pointer to the string pointer.
Thus, you write in a wrong storage area.
My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 6595
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Passing string paramerter by reference to a procedure

Post by mk-soft »

There is only one method to pass strings as byref to a procedure. As a structure with the pointer to the string.

Code: Select all

Procedure foo(*inout.string)
  *inout\s + " World!"
EndProcedure

Define text.string ; <- Define String Pointer Structure

text\s = "Hello"
Debug SizeOf(text) ; Is a pointer to the structure

foo(text) ; <- Adress to the Structure with String Pointer
Debug text\s
My Projects EventDesigner V3 / ThreadToGUI / OOP-BaseClass / Windows: Module ActiveScript
PB v3.30 / v5.75 - OS Mac Mini - VM Window Pro / Linux Ubuntu
Downloads on my OneDrive
User avatar
Piero
Addict
Addict
Posts: 1204
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Passing string paramerter by reference to a procedure

Post by Piero »

Summarizing my Idol with rough code:

Code: Select all

Procedure test(*s.string) 
   *s\s="This is the message"
EndProcedure

test(test.string)
Debug test\s + " outside the procedure"
:wink:
Post Reply