String pointers
BlitzMax Forums/BlitzMax Programming/String pointers
| ||
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. |
| ||
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 |
| ||
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 |
| ||
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 |
| ||
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. |
| ||
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 ;-)* |