I'm embeding PHP in my app (writen in Delphi 2010), using PHP4Delphi component to interface with php5ts.dll. I guess my program acts as extension for the PHP (sapi module?) as it registers some functions and constants which can be used in PHP scripts... anyway, works well when using simple data types, but when I try to use multidimensional array as return value I get error
Access violation at address 01CD3C35 in module 'php5ts.dll'. Read of address 0231E608.
Stack list
(000A2C35){php5ts.dll} [01CD3C35] destroy_op_array + $35
(004C4D61){myApp.exe } [008C5D61] php4delphi.TPHPEngine.ShutdownEngine (Line 1497, "php4delphi.pas" + 17) + $7
The line 1497 in php4delphi.pas is call to tsrm_shutdown();
To me it looks like garbage collector crashing at the end of the script, so I'm suspecting I do not send data correctly back to the engine...
thus my question is how one is supposed to send multidimensional arrays back to PHP?
The pattern I'm using is
var subArray: pzval;
_array_init(return_value, nil, 0);
for x := 0 to Data.Count-1 do begin
subArray := MAKE_STD_ZVAL;
_array_init(subArray, nil, 0);
// populate subarray with data, including other subarrays
...
// add subarray to the main array
add_index_zval(return_value, x, subArray);
end;
Do I have to somewhere "register" the subarrays I create? Do I have to increase or decrease refcount
or set is_ref
? IOW, how must the return_value and zvals of the subarrays to be set up?
I experimented with adding 1 to each array's refcount (althought MAKE_STD_ZVAL already initializes refcount to 1) and that cures the AV but then sometimes app just disappears when executing the script - I suspect it causes infinite recursion in engine's memeory manager, crashing the php DLL and taking the app with it...
When seting refcount to 0 (zero; assuming that when return value is assigned in the PHP script it's refcount will be 1 and then when the PHP variable goes out of scope it will be destroyed) all seems to work (ie no crash, no AV) but the script wont generate any output, just empty html file...
I also send data as arrays into my function, then use zend_hash_find
, zend_hash_get_current_data
etc to read the data. Could this mess up the refcounts of the variables? Ie do I have to decrease refcout of the variable returned by zend_hash_find
when I'm done with it?
And is it safe to reuse same variable when iterating over an array, ie
var Val: pppzval;
new(Val);
zend_hash_internal_pointer_reset(aZendArr^.value.ht);
for x := 1 to zend_hash_num_elements(aZendArr^.value.ht) do begin
zend_hash_get_current_data(aZendArr^.value.ht, Val);
// read data from Val to local variable and do something with it
zend_hash_move_forward_ex(aZendArr^.value.ht, nil);
end;
Dispose(Val);
or should each iteration of the loop create / free Val?
TIA
ain
myFnc(array(array('test')));
all zvals do have refcount 1, however, when calling like$tmp = array(array('test')); myFnc($tmp);
then the zvals at the 2 level (array('test') in this case) do have refcount 2, while all other levels have refcount 1. Using similar refcounts for my return value the AV in original post won't happen, but occasionally app just disappears without any error message... still loos like some sort of mem managing problem, just can't put my finger on it! Any ideas? – MarchpastI just don't want to see it in "Delphi unanswered questions", because I already looked at it
LOL, talk about ego :)and answered it
answer ought to be useful, not just something to get the post out of unanswered list.I believe 6 months is enough time
again, check your math, it's 4 months! – Marchpast