String pointers

BlitzMax Forums/BlitzMax Programming/String pointers

Helios(Posted 2006) [#1]
Hum having a bit of trouble since upgrading to the latest version.

Basically what the problem is, is that in my config system im registering variables with it like this...

	' Adds a new string configuration variable
	Method BindStringCfgVar:TConfigVar(Path:String,Variable:String Var,Index:Int = 0)
	
		' Create new variable
		Local CVar:TConfigVar 	  = New TConfigVar
			  CVar.Path			  = Path
			  CVar.VarType 	   	  = TConfigVar._STRING
			  CVar.StringVariable = VarPtr(Variable)
			  CVar.Index	 	  = Index
						
		' Add it to the list
		ListAddLast(VariableList,CVar:TConfigVar)
	
		' Return the new config variable
		Return CVar:TConfigVar
	
	End Method


And i would write several lines like this to register a my variables.

BindStringCfgVar("Settings::Audio::API",_audio_api,0)


And then when the config system parses the file it would assign the values it finds to the correct variables like so...


		For Local CfgVar:TConfigVar = EachIn VariableList

			' Set value depending on variable type
			Select CfgVar.VarType
			
				' String value
				Case TConfigVar._STRING	
					CfgVar.StringVariable[0] = Scf.GetNodeAsString(CfgVar.Path,CfgVar.Index)						
			End Select
			
		Next	



Unfortunatly i cant do that now as pointers to objects are invalid so i was wandering if anyone knew of another way of doing this, as i really dont want to have a large select block to check what each variable each value should be assigned to.


Dreamora(Posted 2006) [#2]
Ha I knew I would succeed ;-)

Strict

Type Test
	Field name:String
	Field StringVar:Byte Ptr
	
	Method toString1()
		Print "Name: " + name
		Print "StringVar: " + String.fromCString(StringVar) 
	End Method
	
End Type


Local teststring:Byte Ptr	= "Test Ptr".toCString()
Local aka:test 			= New test
aka.name	 		= "test"
aka.StringVar			= teststring

Print aka.tostring1() 

MemCopy(teststring,"Papa".toCString(),Len("Papa")+1)
aka.tostring1()



Hope this helps ... and thank you for the Script Module


Chris C(Posted 2006) [#3]
unfortunatly doing that leaks memory try this


and thry doing the same with your example without the memfree's when your code runs the memory used (as reported by a process explorer continually increases)

using the code I have posted here the mem usage stays stable


Dreamora(Posted 2006) [#4]
You are right.
It was only meant as a general idea on how to get around it. Wrapping it into a function that sets the content would be simpler anyway. For example like

Function SetCString(target:byte ptr, in:string)
	Local ts:Byte Ptr= in.toCString()
	MemCopy(target,ts,Len(in)+1)
	MemFree ts
end function



Helios(Posted 2006) [#5]
Thanks guys that should be helpfull, ill try it out tommorrow


and thank you for the Script Module


Your welcome, always nice to share with the community.


Dreamora(Posted 2006) [#6]
I just realized something: The above method is a really dangerous one!
It can potentially overwrite other objects handled by the GC.

Here a fixed version.
Btw: You need to init the stringptr as well with that size when you create it. I created the init method for that.

Strict
Type CVar
	Field name:String
	Field namePtr:Byte Ptr
	
	Method init(length:Int)
		' Length is the max length of the strings you want to use
		' +1 is needed for the C Stringterminator char (chr(0))
		namePtr	 = MemAlloc(length+1)
	End Method
End Type


Function SetCString(target:Byte Ptr, in:String)
	' Lets say there is a constant max_len that defines the max string len
	Local ts:Byte Ptr
	If in.length > max_len
		in	 	= Left(in , max_len)
		ts		= in.toCString()
	Else
		Local tm:Byte Ptr		= MemAlloc(max_len + 1)
		ts		= in.toCString()
		MemCopy(tm , ts , in.length + 1) 
		MemFree ts
		ts		 = tm
	EndIf 
	MemCopy(target,ts,max_len+1)
	MemFree ts
End Function



Const max_len:Int	 = 20

Local test:cvar = New cvar
test.name	 = "Test"
test.init(max_len)
Print "Memory: " + GCMemAlloced()
For Local i = 0 To 100000000
	setCString(test.namePtr , "Test: " + i)
Next

Print "Memory: " + GCMemAlloced()
End


*sorry that I had to remove the code. had a little nifty memoryleak ;-)*