MemoryBlock - ByRef?

Just want to make sure I’m doing this right as MemoryBlocks are new to me. This is what I understand from simple test.
Passing a MemoryBlock to a Method to change it i.e. “hello” becomes “goodbye” I need to pass ByRef unlike a user defined Class or Object.

The rules for “ByRef” are the same no matter what you’re passing. If you want the original variable that holds the data to be modified, pass ByRef. If not, pass ByVal.

If you are passing an object (like a MemoryBlock), modifying the contents will affect the original value passed.

To illustrate:

dim mb as new MemoryBlock( 100 )
mb.StringValue( 0 ) = "hello"

Sub ModifyIt ( m As MemoryBlock )
  m.StringValue( 0 ) = "Goodbye"
End Sub

mb now contains “goodbye” because its contents were changes by the sub.

Sub ModifyIt (m as MemoryBlock)
  m = "goodbye"
End Sub

mb still contains “hello” because the sub assigned a new MemoryBlock to m, and that instance went away as soon as the sub ended.

Sub ModifyIt (ByRef m As MemoryBlock)
  m = "goodbye"
End Sub

mb now contains a MemoryBlock whose size is 7 that contains “goodbye”. The original MemoryBlock that contained “hello” whose size was 100 is gone.

Well if only it was that simple :slight_smile: But that is great to know for MemoryBlock :slight_smile:

Pushbutton - Action

Sub ChangeCaption (x As Pushbutton)
x.Caption = “What??”
End Sub

It seems like we just went onto a new topic, but that code seems fine.

To put this another way, for future reference, when passing an object, you are actually passing a pointer to the object. When passing ByRef, you are passing a pointer to the variable that holds the object. Even though both techniques give you access to the object, ByRef allows you to modify the original variable too.

(This is probably not technically exact, but illustrates the concept.)

It is that simple. Do you have a problem with some code that you would like to share? Another pair of eyes usually helps.

No, all good just wanted to make sure of ByVal and ByRef with MemoryBlocks as I’ve never used one before and I’m changing a Byte()s from VB6 to MemoryBlocks. Thx.

Might add in the Classic framework you can copy a new memory block from another with a simple function to create two independently variable blocks:

[code]dim mb1 as new MemoryBlock( 100 )
mb1.StringValue = “hello”

dim mb2 as new MemoryBlock( 100 )
mb2 = MemByVal(mb1) //mb2 now says “hello”

mb1.StringValue( 0 ) = “goodbye”
mb2.StringValue( 0 ) = “so long”

Sub MemByVal (strData as String) as MemoryBlock
return strData
End Sub
In the result, mb2 to which “hello” was copied now contains the string “so long” while mb1 contains “goodbye”.

In the new framework it’s simpler:

dim mem1 as new Xojo.Core.MutableMemoryBlock(100)
mb1.CStringValue(0) = “Hello”

dim mb2 as new Xojo.Core.MutableMemoryBlock(mb1) //mb2 now says “hello”

mb1.CStringValue( 0 ) = “goodbye”
mb2.CStringValue( 0 ) = “so long”[/code]

However probably due to fewer steps, the new framework does it 8X quicker (at least on Linux) which may become important when processing lots of data.

Using simple assignment with classic per below is 2.5x slower than copying with the new framework’s MutableMemoryBlock constructor:

[code]dim mb1 as new MemoryBlock( 100 )
mb1.StringValue = “hello”

dim strTemp as String
strTemp = mb1

dim mb2 as new MemoryBlock( 100 )
mb2 = strTemp[/code]

But simply copying between strings looks to be about 15X faster again than copying using the new framework’s memory block constructor. And copying by:

m2 = m1.StringValue(0,99)

is 10x slower than the new framework’s memory block constructor. Just using strings for copying wins hands down.

I figure it might be because copying strings is done natively by the underlying compiler?

When you talk about "copying strings ", what do you mean exactly?

I put 100,000 chars in a string, call it str1
Then in a loop I put of 100,000 iterations:

dim str2 as string  = str1

Was quicker than fastest memory block equivalent by an order of magnitude. Guess there must be quite a bit of overhead creating the object.

The reason that’s so fast is because it isn’t copying the bytes of the string, it’s just assigning a reference to the string.

The equivalent would be

dim mb2 as MemoryBlock = mb1 

Eric, your examples using the old framework are doing way too much work, which is throwing off your comparisons.

At the very least, rewrite your MemByVal function as

dim mb1 as new MemoryBlock( 100 )
mb1.StringValue = “hello”

dim mb2 as MemoryBlock // don’t allocate it, you’re just going to throw it away
mb2 = MemByVal(mb1) //mb2 now says “hello”

mb1.StringValue( 0 ) = “goodbye”
mb2.StringValue( 0 ) = “so long”

Sub MemByVal (oldmb as MemoryBlock) as MemoryBlock
dim newmb as new memoryblock(oldmb.size)
newmb.StringValue(0, olbmb.size) = oldmb.StringValue(0, oldmb.size)
return newmb
End Sub[/code]

Hi Tim, the m2 = m1.StringValue(0,99) I mentioned above was about the same as my function anyway.

Kem, the reason why I thought the strings underneath are copying bytes not just pointers is because they can be changed, or do they only copy when the string is changed so that’s where we pay? If that is so we would pay everytime making strings much sower in total time after the first update. ll have to do an experiment to find out…

No, it’s doing 2 conversions instead of one. Although I suspect that copying byte values with sufficient pragmas to turn of checking would be faster.

But that’s the point. They cannot be changed. Strings are immutable. When you make a change, you get a new string. MemoryBlocks are mutable, so making small changes to a large MB is much faster.