Convert a string into a null-terminated string?

BlitzMax Forums/BlitzMax Programming/Convert a string into a null-terminated string?

Grey Alien(Posted 2007) [#1]
I'm doing some WinAPI stuff and one of the structures is this:

typedef struct _TRUSTEE {
  PTRUSTEE pMultipleTrustee;
  MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
  TRUSTEE_FORM TrusteeForm;
  TRUSTEE_TYPE TrusteeType;
  LPTSTR ptstrName;
} TRUSTEE,  *PTRUSTEE;


Basically LPTSTR ptstrName should be "A pointer to a null-terminated string that contains the name of the trustee"

Well I'm a bit wary of doing this:

Type TTRUSTEE
	Field pMultipleTrustee: Byte Ptr
	Field MultipleTrusteeOperation: Int
	Field TrusteeForm: Int
	Field TrusteeType: Int
	Field ptstrName: String
End Type


Where my ptstrName is a normal BlitzMax string. I'm not convinced it will work. I tried defining it as Byte Ptr but then later I can't do Trustee.ptstrName="User", whereas I can if it's a String.

I know when you do externs you can specify as null terminated string with $z but if I do:

Field ptstrName$z

I get "Illegal variable type" on compile.

This stuff does my head in. Any advice MEGA appreciated, thanks!


JoshK(Posted 2007) [#2]
mystring.ToCString()


Grey Alien(Posted 2007) [#3]
thanks. Seems to work if I declare the field as a Byte Ptr (Field ptstrName: Byte Ptr), that's correct is it? OK so how would I read that back as matter of interest because if I do Print ea.Trustee.ptstrName I get "Cannot convert from Byte Ptr to String".


N(Posted 2007) [#4]
String.FromCString( ptstrName )

You have to free the memory allocated for ptstrName yourself, by the way.


Grey Alien(Posted 2007) [#5]
Neat, works well thanks Noel.

So the GC won't clean that up, OK. How would I free that memory then please?


Azathoth(Posted 2007) [#6]
Depends how you allocated it in the first place.
You also need to use MemFree on the memory returned by mystring.ToCString() when you've finished with it.


Grey Alien(Posted 2007) [#7]
You also need to use MemFree on the memory returned by mystring.ToCString() when you've finished with it.
Isn't that what Noel meant?

So if I do:

Trustee.ptstrName = "Users".ToCString()


after I've used Trustee I should do:

MemFree(Trustee.ptstrName)


Is that correct? And I do that before I set Trustee to Null in order for the GC to deal with it right?

I don't have to do any more MemFree calls just because I've used String.FromCString(Trustee.ptstrName) do I?


Azathoth(Posted 2007) [#8]
Yea, you don't have to necessarily set Trustee to null if its going to go out of scope or you're going to overwrite it.


Grey Alien(Posted 2007) [#9]
Yep I realise that thanks.


N(Posted 2007) [#10]
Grey:
Is that correct? And I do that before I set Trustee to Null in order for the GC to deal with it right?
It's a good idea to also ensure that whatever code is using the pointer makes its own copy of the data if it's stored for use beyond the initial piece where the pointer is used. Otherwise you're going to get some unusual errors.
I don't have to do any more MemFree calls just because I've used String.FromCString(Trustee.ptstrName) do I?
No. The string returned by FromCString is managed by the garbage collector, versus the memory that ptstrName points to which is not.

Azathoth:
Depends how you allocated it in the first place.
No it doesn't, there's only one way to free memory: MemFree.


Azathoth(Posted 2007) [#11]
No it doesn't, there's only one way to free memory: MemFree.
Not if you allocated the memory using the Win32 API.


N(Posted 2007) [#12]
Not if you allocated the memory using the Win32 API.
That's not a good idea.


Azathoth(Posted 2007) [#13]
Because you made reference to 'String.FromCString' I thought you were talking about an external function or some c code allocating the c-string, in which case freeing it would depend on how the function allocated it.


Brucey(Posted 2007) [#14]
No it doesn't, there's only one way to free memory: MemFree.

Not really. If you allocated the memory using malloc() or whatever, you would have to free() it, rather.
And the same goes for however the particular API says the memory should be freed. Sometimes the API allocates the memory, which you must then free.


N(Posted 2007) [#15]
Not really. If you allocated the memory using malloc() or whatever, you would have to free() it, rather.
This is if you expose those functions and any other functions for memory manipulation not provided by BRL. I'm talking specifically about the API provided by BRL, which has only one means of allocating and freeing memory (last I checked -- been a while since I bothered messing with their modules' internals).

Edit: Should be noted, folks, you don't want to use free() on memory allocated by MemFree.


Brucey(Posted 2007) [#16]
True.. if your C String was created via ToCString() you would want to call MemFree() to free it.


Grey Alien(Posted 2007) [#17]
Cool that's what I needed to know. ToCString is a Blitz call and so any memory allocated by it should be freed in a Blitz compatible manner which seems to be MemFree().