Page 1 of 1

Can't get the address of a constant string

Posted: Fri Jul 03, 2009 4:47 am
by Mistrel
You can get the address of a literal string but the PureBasic parser won't let you get the address of a constant string. This should be possible because it will become a literal after the parser performs the constant find/replace.

Code: Select all

*This=@"Hello!"
Debug PeekS(*This)

*This=@#PB_Compiler_File
Debug PeekS(*This)
Otherwise I think this is the only to pass the pointer to a constant resolved string literal to a function by address:

Code: Select all

Procedure This(*String.s)
  Debug PeekI(@*String.s)
EndProcedure

This(?CompilerFile)
This(?CompilerFile)

DataSection
  CompilerFile:
    Data.s #PB_Compiler_File
EndDataSection

Posted: Mon Jul 06, 2009 9:53 am
by helpy

Code: Select all

CompilerIf #PB_Compiler_Unicode
  Prototype ptPassStringPointer( string.p-unicode )
CompilerElse
  Prototype ptPassStringPointer( string.p-ascii )
CompilerEndIf

Procedure procGetStringAddress( *string )
  Debug Str(*string) + "  -  " + PeekS( *string )
  ProcedureReturn *string
EndProcedure

AddrOfString.ptPassStringPointer = @procGetStringAddress()

Debug @"Hello!"                 ; @"Hello!" has the same value
Debug AddrOfString( "Hello!" )  ; as the *string, which is handled in the proc!
Debug ""

;Debug @#PB_Compiler_File
Debug AddrOfString( #PB_Compiler_File )
Debug ""

test.s = "Hello world!"
Debug @test
Debug AddrOfString( test )
Debug ""

Posted: Mon Jul 06, 2009 10:45 am
by srod
That's a neat trick. 8)

Posted: Mon Jul 06, 2009 7:31 pm
by Mistrel
Brilliant! srod is right, this is a neat trick. I wonder what else this could be useful for. Hhmm.. the possibilities. :D

Posted: Tue Jul 07, 2009 12:14 am
by einander
I wonder what else this could be useful for.
You can get also Constants and StringConstants addresses.
Thanks helpy: very useful!

Code: Select all

CompilerIf #PB_Compiler_Unicode
  Prototype ptPassStringPointer(String.p-unicode )
CompilerElse
  Prototype ptPassStringPointer(String.p-ascii )
CompilerEndIf

Prototype ptPassLongPointer(Long.L)

Procedure GetStringConstantAddress(*ConstantS) 
  ProcedureReturn *ConstantS
EndProcedure

Procedure GetConstantAddress(*ConstantL) 
  ProcedureReturn *ConstantL
EndProcedure


#ConstS="This is a string 1234567891233456789123456789"
#ConstL=12345678

AddrOfS.ptPassStringPointer=@GetStringConstantAddress()
AddrOfL.ptPassLongPointer=@GetConstantAddress()

PTRS=AddrOfS(#ConstS)
PTRL=AddrOfl(#ConstL)

Debug "String Constant Ptr "+Str(PTRS)  ; OK 
Debug PeekS(PTRS)

Debug "Long Constant Ptr "+Str(@PTRL)   ;OK
Debug PeekL(@PTRL)

Posted: Tue Jul 07, 2009 6:00 am
by helpy
1. A constant Number does not have an Datatype! It can be assigned to any variable. Why do you think that the constant #ConstL=12345678 is a long?


2. I am not sure, if constant numbers are stored somewhere in an internal data section like strings. I think this is not the case.

Try this code to test this:

Code: Select all

Prototype ptPassLongPointer(Long.L)

Procedure GetConstantAddress(*ConstantL)
  ProcedureReturn *ConstantL
EndProcedure


#ConstL=12345678
#Const2=23456789

AddrOfL.ptPassLongPointer=@GetConstantAddress()

PTRL=AddrOfl(#ConstL)
Debug "Long Constant Ptr "+Str(@PTRL)   ;OK
Debug PeekL(@PTRL) 

PTRL=AddrOfl(#Const2)
Debug "Long Constant Ptr "+Str(@PTRL)   ;OK
Debug PeekL(@PTRL)
Both constants #ConstL and #Const2 would have the same address! This can not be right!

There is a mistake in your code! Not the pointer of the variable is passed to the function, but the value! Try this code:

Code: Select all

Prototype ptPassLongPointer(Integer)

Procedure GetConstantAddress(ConstantL)
  Debug ConstantL
  ProcedureReturn ConstantL
EndProcedure


#ConstL=12345678
#Const2=23456789

AddrOfL.ptPassLongPointer=@GetConstantAddress()

Debug AddrOfl(#ConstL)
Debug ""
Debug AddrOfl(#Const2)
==> In your code you assign the value of the constant to PTRL (which is an integer variable)! ... the value is returned by the function!
==> With Debug Str(@PTRL) the pointer to the variable PTRL is shown!
==> With PeekL(@PTRL) you get the value of the PTRL variable!

This cannot be used to get the pointer of numerical constants, because (1) the value is passed to function (not the pointer) ... and because (2) numerical constants are never stored in an internal datasection (like strings).


3. For strings it is working as long the behavior of Pseudotypes is not changed! If the string, which is passed to the function, has the same string format (the same pseudotype) as the argument, the pointer to the original string is passed to the function.

If the formats are different the string is converted to the other format (given by the pseudotype). And the pointer to this temporary string is passed to the function ... and is only valid for the function itself.

As long PureBasic does pass the pointer to the original string, if the formats are the same, this "workaround" works. But if this behaviour is changed in the future, this will not work anymore!

The pseudotypes are designed to tell the compiler how to pass strings (and also variants) ... and (if necessary) do a conversion of the data.


cu, helpy

Posted: Tue Jul 07, 2009 11:19 am
by einander
@helpy:
My mistake :oops:
Thanks for clarifying and providing excellent examples.

Posted: Sat Jul 11, 2009 6:04 pm
by Psychophanta
helpy wrote:A constant Number does not have an Datatype! It can be assigned to any variable.
Well, don't forget the exception of those which ends in '$' :wink:
For example:

Code: Select all

#holala$=12 ; <- error
#holala$="12"; <- well done!

Posted: Sat Jul 11, 2009 7:25 pm
by Mistrel
Psychophanta wrote:Well, don't forget the exception of those which ends in '$'
I think that's more of a compiler check than a datatype.