Page 1 of 1

Passing string paramerter by reference to a procedure

Posted: Tue Nov 12, 2019 11:51 pm
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

Re: Passing string paramerter by reference to a procedure

Posted: Wed Nov 13, 2019 12:00 am
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



Re: Passing string paramerter by reference to a procedure

Posted: Wed Nov 13, 2019 12:10 am
by RobertRioja
Thank you for your help. I got it to work. I was close... But you were closer.

Robert

Re: Passing string paramerter by reference to a procedure

Posted: Wed Nov 13, 2019 12:29 am
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) 

Re: Passing string paramerter by reference to a procedure

Posted: Wed Nov 13, 2019 8:12 am
by Lord
Why is Global for *StrE.String necessary as you provide the
adress by *StrE to the procedure?
It works without.

Re: Passing string paramerter by reference to a procedure

Posted: Wed Nov 13, 2019 7:38 pm
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) 

Re: Passing string paramerter by reference to a procedure

Posted: Wed Nov 13, 2019 9:30 pm
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

Re: Passing string paramerter by reference to a procedure

Posted: Thu Nov 14, 2019 12:14 am
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

Re: Passing string paramerter by reference to a procedure

Posted: Thu Nov 14, 2019 12:31 am
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


Re: Passing string paramerter by reference to a procedure

Posted: Thu Nov 14, 2019 2:03 am
by idle
thanks wasn't thinking