I would like to store data in a MemoryBlock aligned to 4 bytes, like that:
Dim mb As New MemoryBlock(10 * 4)
mb.Int32Value(0) = aIntegerValue
mb.Int8Value(4) = CType(aByteValue, Integer)
mb.SingleValue(8) = aSingleValue
// and so on for values which take 4 or less bytes
This works fine. And for values using more than 4 bytes (Int64s, Doubles, Strings) I would like to store a pointer to the value
It appears that you can convert a Pointer to a UInt32 value, then stuff that value in the destination memory block, as follows:
dim mb as MemoryBlock = "Testing"
dim mb2 as new MemoryBlock(4)
dim p as Ptr = mb
dim i as Uint32 = Uint32(p)
dim h as string = hex(i) // check this value in the debugger for fun and profit!
mb2.UInt32Value(0) = i
In the debugger you can clearly see that the value of i (when converted to Hex) is the same as p
Michael, you can do this directly with MemoryBlock.Ptr. You don’t need to go through an UInt32.
I just tested this code and it works just fine:
dim mb as new MemoryBlock( 40 )
dim stringMB as new MemoryBlock( 20 )
stringMB.CString( 0 ) = "some string" + ChrB( 0 )
dim p as Ptr = stringMB
mb.Ptr( 0 ) = p
dim doubleMB as new MemoryBlock( 8 )
doubleMB.DoubleValue( 0 ) = 3.123
p = doubleMB
mb.Ptr( 4 ) = p
p = mb.Ptr( 0 )
dim newMB as MemoryBlock = p
dim s as string = newMB.CString( 0 )
newMB = mb.Ptr( 4 )
dim d as double = newMB.DoubleValue( 0 )
Kem, the LR says “MemoryBlock.Ptr: Returns a MemoryBlock with an unknown size. It sets Size to -1 but it still can be used to access its data. Offset is in bytes from the beginning of the MemoryBlock.” It says nothing about using Ptr(offset) as a Setter.
So either you are just creating a new memory block (in which case that code probably doesn’t work), or perhaps the LR is incorrect?
Kem Tekinay: Thanks Kem, works well. My mistake was that I didn’t realize that MemoryBlocks get released as any other variable when they go out of scope from where they were declared. So I just add these MemoryBlocks for values which need 8 or more bytes to an array, and now I can use them everywhere in my class.
I think there might be some fundamental confusion, so I’ll start at the top.
A Ptr is a representation of an address in memory. Every item that is stored has such an address, but in Xojo, you can get the address for such things as a MemoryBlock or method.
A MemoryBlock is reserved spot in memory of a given size into which you can store and retrieve bytes. A new MemoryBlock starts initialized at all zeros.
When you store MemoryBlock.Ptr, you are storing the address (currently 4 bytes) of the item. When you retrieve that Ptr, you are retrieving that address.
When you retrieve the address as a MemoryBlock, there is no way for the system to know how big the MemoryBlock is, so its size is set to -1, effectively “infinite”, so it’s up to you to know how much of the memory you are actually using.
If you create a new MemoryBlock(4) and immediately retrieve p = mb.Ptr(0), you will end up with an infinite MemoryBlock starting at address &h0000, which is effectively useless and potentially dangerous.
Looking at it another way, when you retrieve a MemoryBlock.Ptr, you are saying, “show me the bytes that start at that address.” If the address is random, the results will be meaningless, but it won’t be a “new” MemoryBlock.
No, but that’s OK, I think we are talking across each other.
The issue I’m having is that the old LR was incorrect : it said that MemoryBlock.Ptr(offset) would create a new memoryblock at the offset. That wasn’t true : what actually happens is that MemoryBlock.Ptr(offset) would use the 4 bytes stored at MemoryBlock(offset…offset + 3), convert that to a pointer, which is entirely not the same thing. (In C terms, it’s the difference between &ptr and *ptr ). You edited the LR now so that’s OK.
Of interest, if you do the test you proposed:
dim mb1 as new MemoryBlock(4)
dim p1 as Ptr = mb1.Ptr(0)
A nilObjectException is triggered, which is interesting - a little unexpected but not insane.
Here’s how I would clarify things in the LR, by adding this sentence:
Note the difference in function between setting a Ptr to equal a MemoryBlock vs. using the MemoryBlock.Ptr(offset) function: In the first case, the Pointer will point to the MemoryBlock itself; in the latter case, the Pointer will be set to the value of the 4 bytes stored inside the memoryBLock from offset to offset+3. The pointer will not point to the address of those bytes.
When you say, “the test you proposed,” where did you see that code? I don’t recall writing that, and it’s not in the LR, at least not like that. I wouldn’t want someone to do that, so I’d like to clean it up.
As for your proposed addition, point taken. I’m writing a bit a differently, but you’ll be able to see the change soon. Feel free to comment.
In the prior post where you said “If you create a new MemoryBlock(4) and immediately retrieve p = mb.Ptr(0)”
Late night? Your caffeine to blood ratio too low?
No, what you “quoted” and what I wrote were different enough that I didn’t make the connection, but that’s fine. I just wanted to make sure I didn’t inadvertently include something like that in the LR. It’s all good.