Byref‘ing an Array from an API call?

Hello all,

how can I use a Cocoa function that delivers its result in form of byrefs if one of them is an array?

I can pass an array to the function, but in returning I made an error and do not know how to handle this:

[code]Attributes( “not working yet!” ) Sub getLineDash(byref pattern() as single, byref count as Integer, byref Phase as single)
// Returns the line-stroking pattern for the receiver.

// not working!

dim patternarray as new memoryblock (pattern.ubound + 1 * 4)
dim patternpointer as ptr = patternarray

// with a similar method I can receive the array for the setLineDash function – I create a memory block, fill it with the singles and pass a pointer to the function call.

#if TargetMacOS
Declare Sub getLineDash lib Cocoalib selector “getLineDash:count:phase:” (obj_ID as Ptr, byref patternpointer as Ptr, byref count as integer, byref phase as single)
getLineDash (self, patternpointer, count, phase)

dim returnarray as MemoryBlock = patternpointer 
// but this does‘t work. patternpointer is changed, but when I view it in Debugger it seems to point to an empty area.

msgbox str(returnarray.Size)+", "+str(count) +", "+str(Phase) 

// therefore I can see in the msgbox that count and phase have changed correctly but not returnarray.

// and then a rebuild of pattern() would have to take place here in order to forward the data.

#endif
End Sub[/code]

Any ideas?

  • Remove ByRef from Byref patternpointer as Ptr in the declare.
Declare Sub getLineDash lib Cocoalib selector "getLineDash:count:phase:" (obj_ID as Ptr, patternpointer as Ptr, byref count as integer, byref phase as single)
  • The way you calculate the patternarray memory block length doesn’t make sense to me. You calculate it by calling getLineDash:count:phase: with the first argument set to 0. You then get the length of the array in the count argument.

Thanks, Eli, I will try that!
And yes, you‘re right: This was just for testing purposes. Of course I need to set up a memory block from the passed pattern().

No, that didn‘t help, Eli – but thanks a lot for suggesting! Patternpointer according to Apple Docs needs to be referenced as byref; the function call changes it. It does so for the other both parameters correctly, but the modified pointer always points into limbo. Count is something that‘s forwarded by the programmer and is set via byref by the Function. I tried to set up a new array like in the set method to be sure but the pattern pointer returned is always &h40A00000.
The error lies in there, not in maybe the nsobject call being senseless (this could be too).

Don‘t worry that patterncount is useless here.

Attributes( “not working yet!” ) Sub getLineDash(byref pattern() as single, byref count as Integer, byref Phase as single)
// Returns the line-stroking pattern for the receiver.

// not working!

const sizeofsingle=4
dim patternCount as Integer = pattern.ubound+1
dim patternarray as new MemoryBlock(count * sizeOfSingle)
for i as integer = 0 to count-1
patternarray.SingleValue(i*sizeOfSingle) = pattern(i)
next

dim patternpointer as ptr = patternarray

#if TargetMacOS
Declare Sub getLineDash lib Cocoalib selector “getLineDash:count:phase:” (obj_ID as Ptr, byref patternpointer as Ptr, byref count as integer, byref phase as single)
getLineDash (self, patternpointer, count, phase)
patternarray = Cocoa.NSObjectFromNSPtr (patternpointer, true, true)
msgbox str(patternarray.Size)+", “+str(count) +”, "+str(phase)
// pattern = returnarray
#endif
End Sub

(Sorry, forgot the code formatting)

From you OP I thought you wanted to get the details of the dashed line.

If you want to set the details, why not use setLineDash:count:phase: and name your method accordingly?

Then there is an error in setting the memory block:

For i As Integer = 0 to Count - 1 patternArray.SingleValue(4 * i * sizeOfSingle) = pattern(i) // positions in MemoryBlock are 0, 4, 8, 12, ... Next

And then I would remove the following line and use the patternArray variable directly - since a MemoryBlock is a Ptr:
Dim patternPointer As Ptr = patternArray
… and it should work by removing ByRef on the patternPointer parameter as I suggested in my first answer.

Thanks a lot again, Eli!

That a memory block is a pointer as well is something that I need to memorize better – this still confuses me.
The Call would‘t let me byref a memory block, that‘s why I tried with the pointer first.

No, you were right, I am using get, not set. The set method works.
Get wants to return 3 values as byrefs.

But why (4 * i * sizeofsingle)? That‘s 16 * i !!??

I think you set my on the right track! I should read the docs more thoroughly. The call modifies the memoryblock but cannot extend it, so I need to call the API twice: Once to check “Count” and set up a memoryblock large enough to contain count Singles, and then a second time for the results. I guess that‘ll do it. I‘ll let you know, but many thanks already!

How embarrassing for me… Doppelt gemoppelt hält nicht in jeden Fall besser.

I‘m glad you haven‘t discovered on of my awful misconceptions … :smiley:

As Trostpflaster – vielen Dank nochmals, ohne dich hätte ich‘s nicht hinbekommen: