Help! - C array of strings!

BlitzMax Forums/BlitzMax Programming/Help! - C array of strings!

Scaremonger(Posted 2010) [#1]
I'm very stuck! Maybe it's late or I'm missing something, but I have a callback routine from a C library that is defined like this:
void callback( DWORD dwArgc, LPTSTR *lpszArgv )

dwArgc - Number of strings in array
lpszArgv - Array of strings

In BlitzMax I've defined the callback function like this...
Function _callback( dwArgc:Int, lpszArgv:Byte Ptr )

But how do I get at the array of strings?

Cheers all...


Gabriel(Posted 2010) [#2]
If you don't particularly like pointer arithmetic, make a static bank from the Byte Ptr, and then use PeekInt (cast the result to Byte Ptr) the number of times held in dwArgc to get the pointer to each string. Then use FromCString to convert each pointer to a string. Or FromWString it it's a wide string.


N(Posted 2010) [#3]
Considering those are Windows types, maybe you should link to an MSDN page covering what that callback is used for so everyone knows what exactly it is that you're supposed to be doing.


Brucey(Posted 2010) [#4]
Something like this might work...
For local i:int = 0 until array_length
    Print String.FromCString(Byte Ptr(Int Ptr(charArrayPtr) + i))
Next

Untested, but something like that, I suppose.


Otus(Posted 2010) [#5]
Are you supposed to pass a string array or receive one? In case the former, something like this:
Local strings:String[] ' = blah

Local cstrings:Byte Ptr[strings.length]
For Local i:Int = 0 Until strings.length
  cstrings[i] = strings[i].ToCString()
Next

_callback cstrings.length, cstrings

For Local i:Int = 0 Until strings.length
  MemFree cstrings[i]
Next



Scaremonger(Posted 2010) [#6]
You guys Rock! I'll take a look tonight.


Scaremonger(Posted 2010) [#7]
Ok. Home at last :)

So, in theory; if we slam together both those bits of code we can test it? Sadly it didn't work :( and I can't figure out whats wrong with it...
Local strings:String[] = ["Scaremonger","Was","Here"]
Local cstrings:Byte Ptr[strings.length]
Local i:Int

For i = 0 Until strings.length
  cstrings[i] = strings[i].ToCString()
Next

_callback cstrings.length, cstrings

For i = 0 Until strings.length
  MemFree cstrings[i]
Next

'##########
Function _callback( array_length:Int, charArrayPtr:Byte Ptr )
	
  For Local i:Int = 0 Until array_length
    Print String.FromCString(Byte Ptr(Int Ptr(charArrayPtr) + i))
  Next

End Function

So I tried @Gabriels suggestion and it works nicely...
	Function _callback2( dwargc:Int , lpszargv:Byte Ptr )
	Local bank:TBank 
	Local str:Byte Ptr
		'# Create a static bank from the byte ptr.
		bank = CreateStaticBank( lpszargv, dwargc )	

		'# Get the strings
		For index:Int = 0 To dwArgc -1
			str = Byte Ptr( PeekInt( bank, index*4 ))
			Print String.fromCstring( str )
		Next
	End Function



Scaremonger(Posted 2010) [#8]
A moment of inspiration and I fixed @Bruceys version...

Function _callback( array_length:Int, charArrayPtr:Byte Ptr )
	
  For Local i:Int = 0 Until array_length
    Print String.FromCString(Byte Ptr((Int Ptr(charArrayPtr) + i)[0]))
  Next

End Function


Thanks for all the help guys :)


Brucey(Posted 2010) [#9]
Here's a working version - now that I've actually tested it ;-)
Print String.FromCString(Byte Ptr(Int Ptr(charArrayPtr)[i]))



Evil Roy Ferguson(Posted 2010) [#10]
Isn't the type of lpszArgv really a Byte Ptr Ptr?

LPTSTR is 'basically' a typedef for char*, thus LPTSTR* is basically char**.

Byte Ptr Ptr is perfectly valid BlitzMax and is probably easier to deal with than using so many casts or using banks.

If lpszArgv were a Byte Ptr Ptr, I believe that stringifying an element of the "Char Array Array" would simply be:

String.FromCString(lpszArgv[i])


(although I'm not able to test right now...)