byte arrays / strings passing to objects confused
Chip Cox
Posts: 73
I always hated type casting in C and now it's here too.· From what I understand when arguements are passed to objects subroutines, they are passed as longs and long arrays.· Furthermore, the variables for the function are all longs and long arrays too.· Even though the calling function may be using bytes and byte arrays and be expecting bytes and byte arrays.· In addition, there seem to be a variety ( at least 2 ) different ways of type casting back to byte.· My question is this, when do I have to cast my variables back to bytes and which form of casting do I use???· Also, it seems the way strings are passed back from functions is through a pointer to a global variable in the object.· What happens if multiple cogs call the same object at the same time.· Also, what happens if you try to nest calls to functions that all pass back strings?· For example· resstr:=str.strpad(str.i2a(buff[noparse][[/noparse]i]),2,"0",LEFT)· Doesn't the return variable get trounced????· I'm getting a headache <grin>.·
Comments
Cogs cannot call functions in another cog (please correct me if I'm wrong about this).· Communication between cogs is done using hub variables.· A cog can cause a function to be performed in another cog by setting a setting a parameter in cog memory.· However, the other cog must examine that variable in a polling loop and execute the proper function based on the value of the parameter.
I don't understand your example about processing a string.· Can you include a short program that demonstrates the problem?
Dave
inbuff[noparse][[/noparse]0]:=9
inbuff[noparse][[/noparse]1]:=8
inbuff[noparse][[/noparse]2]:=3
hld:=str.numbertodecimal(inbuff[noparse][[/noparse]0],2)
hld[noparse][[/noparse]2]:=str.numbertodecimal(inbuff[noparse][[/noparse]1],2)
hld[noparse][[/noparse]4]:=0
debug.str(hld)
numbertodecimal is in stringEngine from the object exchange. It converts a number to a decimal representation of that number in a string the length of the last arguement ( 2 in this case ), zero padded. Lets just say the results I am getting are varied. In this example debug.str(hld) comes out as 08 08.· Yes there is a space between them ( why )??· To my increasingly feeble mind, I think it has something to do with long vs byte alignment, but I'm not sure anymore.
Dave
In SPIN you can ONLY return one long from SPIN functions. Nothing else ... no byte, no word, no array, no string ....
So, if you need to return more than that, you have to return a pointer to the memory where the result can be found. And that's what numberToDecimal is doing. It prepares the string in it's own buffer and returns the address to that. If you call numberToDecimal·a second time, it will overwrite the previous result.
So, what you have to do in your code is:
call numberToDecimal, copy the result to your hld-array @hld[noparse][[/noparse] 0 ], for example using the bytemove instruction.
call numberToDecimal again and copy the result to hld[noparse][[/noparse] 2 ].
·
CON
_clkmode = xtal1 + pll16x ' use crystal x 16
_xinfreq = 5_000_000
OBJ
Str: "StringEngine"
Debug: "Extended_FDSerial"
var
long stack[noparse][[/noparse]1024]
byte cog
PUB main | curtim[noparse][[/noparse]8], hld, inbuff[noparse][[/noparse]40]
Debug.start(31, 30, 0, 115200)
waitcnt((clkfreq*5)+cnt)
inbuff[noparse][[/noparse]0]:= 9 'GPS.rx 'time(1000) ' using hard coded values to test with
inbuff:= 8 'GPS.rx 'time(1000) ' using hard coded values to test with
inbuff:= 4 'GPS.rx 'time(1000) ' using hard coded values to test with
debug.dec(inbuff[noparse][[/noparse]0]) ' prints 9 just like it should
debug.dec(inbuff) ' prints 8 just like it should
debug.dec(inbuff) ' prints 4 just like it should
debug.str(string(13))
hld:=str.numbertodecimal(inbuff[noparse][[/noparse]0],2) ' I think this puts the address of the result from numbertodecimal in hld
debug.str(hld) ' this prints 09 like it should
bytemove(@curtim[noparse][[/noparse]0],@hld,2) ' I think this should move the first 2 bytes of whatever hld points to into the
' first 2 bytes of curtim.
hld:=str.numbertodecimal(inbuff,2)
debug.str(hld) ' this prints out 08 like it should
bytemove(@curtim,@hld,2)
hld:=str.numbertodecimal(inbuff,2)
debug.str(hld) ' this prints out 04 like it should
bytemove(@curtim,@hld,2)
curtim[noparse][[/noparse]6]:=0 ' make sure we have a zero terminated string
debug.str(string(13))
debug.str(string("strtime="))
debug.dec(strsize(curtim[noparse][[/noparse]0])) ' prints out 3
debug.str(curtim[noparse][[/noparse]0]) ' prints out 04
interestingly also, there is a space between the 3 and the 04 ( 3 04 ). Why???
hld already contains the address, so you should use hld only - without @.
bytemove with @hld will copy the address stored in hld to curtim and not the content at this address.
You define curtim and inbuff in the function. This will use a long for each array-element instead of a byte which is what you need. AND it eats up stack-space. So, whenever your stack gets to small, you will have lot's of trouble and best thing ... you'll never guess where the trouble comes from.
Put these variables into VAR-section. Then the compiler can warn you if you run out of RAM. And use byte arrays.
Oh ... now that I mention it ... this is also a bug in your program. bytemove does not care about the datatypes. So it will copy a byte array (the buffer returned by numberToDecimal) into a long array ... depending on what you do with the curtim array that might cause other problems!
Thanks for your help..
Thanks Again.
As I said ... if you use local variable you will somewhen step into unpredictable problems where you simply don't know where these come from.
If you put the buffers into VAR sections and create an array of objects, you can have several instances running the same code, not stepping into each other as well. The good thing is that the compiler can tell you if you run into RAM problems. The stack-version will never complain and simply overwrite what ever is in it's way.
A functions local variables are good for local counters and 'working' variables or 'helper' variables that are only needed inside of one function.
Ok ... let's talk about the code you posted before:
I don't see any COGNEW, so why do you need a stack variable? The first COG will use the whole free memory as stack-space ... no need to initialize a stack for that one, it's only needed for all additional COGs you start.
hld is fine for me, because it's a temporary variable you use inside of main. But the curtim and inbuff should not be defined as local variable. Put em into the var section and use byte as type. If you have additional functions that need independent buffers then use different·buffer-names.
Again ... I think having the compiler checking the RAM-usage is worth to get familiar with other concepts of variable usage. When you start overwriting memory because the stack is to small to hold all the local variables then you will need another 3 days ... or more .. what can go wrong in this case is simply unpredictable up to being destructive.
·
Why would it do that? If you are accessing memory in byte sized quantities alignment is a non-issue. It's only word and long you need to worry about your alignment.
An array of longs is just a pool of bytes, use it however you like.
This simply allocates a pool of ram. It could be long[noparse][[/noparse]25] / word[noparse][[/noparse]50] or byte[noparse][[/noparse]100].
Use it as byte[noparse][[/noparse]@data][noparse][[/noparse]index] to get access to it as a byte array.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You only ever need two tools in life. If it moves and it shouldn't use Duct Tape. If it does not move and it should use WD40.