String Pointers

BlitzMax Forums/BlitzMax Programming/String Pointers

Streaksy(Posted 2012) [#1]
Hours and hours and hours on Google, and nothing.

I'm getting in to this BMax thing and the pointers system is very tricky. I'm fresh from Blitz3D. Am I being stupid?


I've manged to: Access a string's contents from it's pointer

I need to: discern the string's length from it's pointer

The first four bytes from the pointer are the same no matter the string length or contents, and the string characters aren't terminated in a predictable way.

If you're wondering what this is all about, I'm making a console system with a list of console variables which are really pointers to BMax variables. I've got it working for all standard data types except string. So far it's reading the numerical variables fine, and I don't even know how I'm going to set variables using just the pointer...

Any info would be great. I'm at a stand-still. ;/


ziggy(Posted 2012) [#2]
i'm curious t know why you can just use the built-in string Length method. Anyway, can't help here but taking a look to the implementantion of the Lenth method in the BlitzMax source code can enlighten you. Also, you can use the toCString method to have zero terminated strings, but you'll have to handle references to them manually, as they're unmanaged and never collected by the GC.


Streaksy(Posted 2012) [#3]
I've tried the FromCString thing... Can't really get better results with it.

Length method? Okay... imagine you have a string but you also need to manipulate it purely with a pointer to it. There's no length method to go with the pointer. See the problem?

I have a list of console variable objects, with these fields:

VariableName:String
VariablePointer:Byte Ptr

The system is so that you can access BMax variables from within an in-game console. I could of course just have a VariableValue$ field but that's not very portable.

Say you have a variable like Gravity:float... and you want the in-game console to be able to maniipulate it... I'd use:

Global Gravity:Float
AddCVar "Gravity",Gravity

I don't know if you're familiar with in-game consoles... Well anyway, I've scoured the source code for something that handles the string type and I just can't find it. Do you know where it will be?


skidracer(Posted 2012) [#4]
Strings are immutable in BlitzMax so you can't modify them in place.

Even if you find a way of poking around and changing their value you will just end up causing the garbage collector to explode at some random amount of time in the future.


Streaksy(Posted 2012) [#5]
Haha, it was really starting to seem like that. Okay, thanks a lot. I'll do it the slightly less convenient way.


col(Posted 2012) [#6]
If I understand what you're trying to do....

All strings in a game written in c/c++ should end with a Null character. You only need to pass the length if you don't use a Null on the end. You'd have to convert back to a string to then find its length.

To pass out a string you can use

StringPtr:Byte Ptr = "String Variable".ToCString()
MemFree StringPtr 'remember to use this to free the memory

This will allocate some new space in memory and the StringPtr variable will be that address which holds a C style Null terminated string of characters, so it has the extra Null on the end. Because this allocates new memory you need to free that yourself with MemFree.

To get a string back from memory you could use

Variable$ = String.FromCString( StringPtr )
Print Variable$.Length 'Length MINUS the Null character.

Hope this helps.

Last edited 2012


Streaksy(Posted 2012) [#7]
Yeh, but it's supposed to be able to casually link to any BMax string. There's no "passing out", if I understand your meaning of that.

There's just:

Global astring$ = "test string contents"
AddCVar "teststring", astring$

Then in-game, in the console, type "echo teststring" and it should print "test string contents"


skidracer(Posted 2012) [#8]
Just keep well away from brl.mod/blitz.mod/blitz_string.h and you should be OK.


Streaksy(Posted 2012) [#9]
Ah, cheers. Weird that the struct doesn't match my experience at all.

struct BBString{
BBClass* clas;
int refs;
int length;
BBChar buf[];
};

From the pointer, the structure I'm seeing is 4 bytes that are always the same (probably a class signal), then the character data, and some unpredictable yet often similar characters that I'm too scared to mess with.


col(Posted 2012) [#10]
Strings are treated as objects so you'd need to handle the strings differently by converting them to a mem address via the method I suggested, which then breaks your idea of 'casually linking' unfortunately.


Streaksy(Posted 2012) [#11]
I wish it was just:

Local Name$
Local NamePointer:TPointer = GetPointer(Name$)
NamePointer.SetData "Mandy"


At least I've got it working with numericals. I'll just have two kinds of console variable. Linked numerical ones, and console string variable types that contain the string field instead of linking to a string. Really makes it inelegant.


col(Posted 2012) [#12]
It's worth playing around with your idea, I'm sure it could be made to work, but you may need to tread carefully.

A long while ago I saw some BMax code that was indexing into a c++ vtable to alter class method pointers and stuff, seemed like real voodoo at the time as I didn't understand it back then, so anway, I'm sure this can be done with some good knowledge and coding and some time experimenting, but as far as 'out of the box BMax' goes.... it doesnt support this.

Last edited 2012


Streaksy(Posted 2012) [#13]
Good knowledge isn't one of my assets


ziggy(Posted 2012) [#14]
If you want to manipulate BlitzMax variables at runtime, from a console or the like, I would suggest you to use Reflection. This will give you access, not only to varibles, but also to classes and you'll be able to call methods and functions, etc. I think it is a much more convenient way to do that without breaking garbage collection.

Last edited 2012


Streaksy(Posted 2012) [#15]
BTW, I have it working with a sort of work-around, but I dunno how reliable it is.

String data, directly read from 4 bytes after the pointer, so far, has always ended in a char with a 4-or-5 digit code always starting with 37##. So, I've actually had it working this whole time but I've no idea if it's safe to rely on strings always being terminated with such a character. Like I said, I can get to the data. It's just the string length I can't reliably discern.

My whole idea is prolly pointless anyway because, even if I figure out how to get string length etc, I don't even know where to start when it comes to SETTING the data instead of just getting it.

Last edited 2012


Streaksy(Posted 2012) [#16]
Reflection... Don't know anything about that. Eugh, too tired to look in to it now. I'll investigate reflection tommorow. cheers.