【发布时间】:2011-08-12 07:28:25
【问题描述】:
我在我的应用程序中嵌入了 PHP(用 Delphi 2010 编写),使用 PHP4Delphi 组件与 php5ts.dll 进行交互。 我猜我的程序充当 PHP(sapi 模块?)的扩展,因为它注册了一些可在 PHP 脚本中使用的函数和常量……无论如何,在使用简单数据类型时效果很好,但是当我尝试使用多维数组时作为返回值我得到错误
Access violation at address 01CD3C35 in module 'php5ts.dll'. Read of address 0231E608.
堆栈列表(000A2C35){php5ts.dll} [01CD3C35] destroy_op_array + $35(004C4D61){myApp.exe } [008C5D61] php4delphi.TPHPEngine.ShutdownEngine (Line 1497, "php4delphi.pas" + 17) + $7
php4delphi.pas 中的第 1497 行调用tsrm_shutdown();
在我看来,垃圾收集器在脚本结束时崩溃了,所以我怀疑我没有正确地将数据发送回引擎......
因此我的问题是应该如何将多维数组发送回 PHP?
我使用的模式是
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;
我必须在某个地方“注册”我创建的子数组吗?我必须增加或减少refcount 还是设置is_ref? IOW,如何设置子数组的return_value和zvals?
我尝试将 1 添加到每个数组的 refcount(虽然 MAKE_STD_ZVAL 已经将 refcount 初始化为 1)并且可以治愈 AV 但有时应用程序在执行脚本时会消失 - 我怀疑它会导致引擎的内存管理器中的无限递归,导致 php DLL 和随身携带应用程序...
当将 refcount 设置为 0(零;假设在 PHP 脚本中分配返回值时,它的 refcount 将为 1,然后当 PHP 变量超出范围时,它将被销毁)似乎一切正常(即没有崩溃,没有 AV ) 但脚本不会生成任何输出,只是空的 html 文件...
我还将数据作为数组发送到我的函数中,然后使用zend_hash_find、zend_hash_get_current_data 等读取数据。这会弄乱变量的引用计数吗?即,当我完成它时,我是否必须减少 zend_hash_find 返回的变量的 refcout?
遍历数组时重用相同的变量是否安全,即
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);
或者循环的每次迭代都应该创建/释放 Val?
TIA
是的
【问题讨论】:
-
经过一些实验后,我注意到了奇怪的(?)事情 - 当使用像
myFnc(array(array('test')));这样的“直接值”调用我的函数时,所有 zval 确实有 refcount 1,但是,当像$tmp = array(array('test')); myFnc($tmp);这样调用时,zvals在第 2 级(本例中为数组('test'))确实有 refcount 2,而所有其他级别都有 refcount 1。使用类似的 refcounts 作为我的返回值,原始帖子中的 AV 不会发生,但偶尔 app 会消失没有任何错误消息...仍然像某种内存管理问题一样,只是无法解决!有什么想法吗? -
有什么关系,是打开还是关闭?诚实的问题,我在这里比较新。
-
Sam,你真的读过我的帖子还是只是数了问号?是的,我想修复 AV - 这基本上就是阻止我使用多维数组的原因。我担心内存管理,因为我怀疑这是问题的根本原因。我提到在数组中发送数据,因为我怀疑这可能是问题的一部分,即我没有正确访问它们,因此搞砸了内存管理器,这反过来又导致我的函数返回的数组出现问题(我现在很确定事实并非如此)。哦,关闭问题的建议现在已经被作者删除了?
-
对不起,Sam,但您似乎还没有阅读我的 OP - 第一段回答了您的问题。扩展功能是我用Delphi写的,当然有源代码可以修改。函数的名称和定义无关紧要,因为所有扩展函数都具有相同的签名。我引用的 DLL (php5ts.dll) 是我尝试使用/嵌入的 PHP 引擎(它来自标准发行版,而不是自定义构建)。山姆,感谢您的帮助,但在我看来,您对手头的主题并不熟悉...
-
@EMBarbosa 两个问题都没有。这个功能对我来说不是必须的,所以我现在已经停止了积极的调查......我仍然想让它工作,但目前它在待办事项列表中的位置很低。
标签: delphi delphi-2010 php-extension php-internals php4delphi