I'm suspicious of your declaration of the ppPins parameter and your casts to TPointerDynArray and TIPinDynArray.
I'm suspicious of your declaration of the ppPins parameter and your casts to TPointerDynArray and TIPinDynArray. You will get range errors if you pretend that the array passed in is a Delphi dynamic array when in fact it is not. Delphi dynamic arrays have a block of memory that precedes the first item of the array and identifies the reference count to the array, and it's length.
Since this block is missing in your array, tricking the compiler into believing it is there will result in the error you see. I'd do it as shown below. This matches the declarations used in MSDN.
You have to use a bit of pointer arithmetic but I believe it is easier to do this since your code now will be easy to relate to any C++ samples you can find online. Type PIPin = ^IPin; function TBCEnumPins. Next(cPins: ULONG; ppPins: PIPin; pcFetched: PULONG): HRESULT; begin ... // this is the meat of the loop, assign to the output array, and increment Pointer(ppPins)^ := nil; // initialise the intf ref to avoid bogus _Release ppPins^ := Pin; inc(ppPins); ... end.
I'd explain the code but as I said, that's the stock code that came with DSPACK so I don't know the reasoning behind it's structure. Note the "range check error" is a known error on the DSPACK (progdigy) forums. I'll give your code a try.
– Robert Oschler Oct 29 at 8:31 @Robert I added one line of code. I realised I missed the fact that the array needs to be zero initialised to avoid Delphi writing in calls to _Release on uninitialised references. To be honest that's probably easiest with a call to FillChar or ZeroMemory outside the loop.
– David Heffernan Oct 29 at 9:09 Heffeman. Please see my comment to Roman in his reply, about the "out" parameter/NIL combination. – Robert Oschler Oct 29 at 9:32 @Robert ppPins should never be NULL.
And I mean ppPins as per MSDN, not in your code. It would be so much easier if you answered my question about what really is NULL. Anyway, it's clear that your original code is wrong when range checking is on.
I do believe that my answer explains everything you have repored. – David Heffernan Oct 29 at 9:51 Heffeman. As I said, it isn't my code.It's part of the DSPACK BaseClass unit.
PpPins can be NIL if that's what happens to be in the destination buffer when the caller calls TBCEnumPins.Next(). If it is NIL then when range checking is on, it is treated as a zero length array. The NIL is just what happens to be at the start of the destination buffer pointed to by ppPins.
By taking the address of an "out" (by reference) parameter, the original author in essence is pointing to the start of the destination buffer that will receive the fetched pin. See my "update" to my original post. – Robert Oschler Oct 29 at 10:13.
IEnumPins::Next method is not supposed to be called with ppPins == NULL. The best way to handle is thus return immediately with E_POINTER error code. You might want to check caller's code to find out why you have NULL there in first place.
I actually doubt that ppPins really is NULL. If it was then there would be access violation rather than range error. It's also complicated by the fact that the COM declaration of ppPins is a pointer to an IPin but the code in the question uses an out parameter in a dubious way.
– David Heffernan Oct 29 at 8:07 Agree. Talking about range checking, it looks like the problem might come up if caller requests 2+ pins to be enum'med at once, and the function is defined in a way that ppPins is a single value, not an array. Still, OP asked about NULL argument and here we go.
I supposed that calling code is not external, and OP might be having a problem on caller side within his own code. – Roman R. Oct 29 at 8:25 @David Heffernan.
Are you sure an A/V would necessarily be fired here? Delphi treats NIL array as zero length and if the compiler treated it as such first, a range check error would be fired before an access violation when the index is applied to the empty array since it is zero length. – Robert Oschler Oct 29 at 8:35 @RobertOschler Yes you are correct.My mistake.
But you must take my point about this misuse of dynamic arrays. Perhaps the sample code you copied works with range checking off. – David Heffernan Oct 29 at 8:41 1 In the code snippet behind the link above ppPins would never be NULL, it is always a valid pointer.
– Roman R. Oct 29 at 9:34.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.