php - 从 C 调用 PHP 函数后扩展中的 Seg 错误
问题描述
我正在尝试编写一个扩展,在做完事情后回调一个 PHP 函数。为了检查可行性,我按照这篇文章去了:https ://devzone.zend.com/303/extension-writing-part-i-introduction-to-php-and-zend/
基本扩展工作正常。然后我添加了代码来调用 PHP 函数,如下所示:
PHP_FUNCTION(hello_world)
{
zval p1;
INIT_ZVAL(p1);
ZVAL_STRING(&p1, "From extension", 1);
zval *params = { &p1 };
zend_uint param_count = 1;
zval *retval_ptr = NULL;
zval function_name;
INIT_ZVAL(function_name);
ZVAL_STRING(&function_name, "from_ext", 1);
if (call_user_function(
CG(function_table), NULL /* no object */, &function_name,
retval_ptr, param_count, ¶ms TSRMLS_CC
) == SUCCESS
) {
printf("Success returning from PHP");
if (retval_ptr)
zval_ptr_dtor(&retval_ptr);
}
/* don't forget to free the zvals */
zval_dtor(&function_name);
zval_dtor(&p1);
RETURN_STRING("Hello World", 1);
}
和调用PHP:
<?
function from_ext($arg) {
echo "In PHP:", $arg;
return "hello";
}
echo hello_world();
?>
它确实调用了 PHP 函数并且可以看到该值,但之后会引发 Seg 错误:
php -dextension=modules/hello.so test.php
In PHP:From extensionSegmentation fault: 11
我正在使用附带的 PHP(5.6.30)在 MacOS 10.12.6 上进行尝试。
知道如何克服 Seg 故障吗?
解决方案
您需要zval
在堆栈上分配返回值。传入的指针call_user_function
必须为非 NULL。这是一个应该解决问题的补丁。
--- a/mnt/tmpdisk/a.c
+++ b/mnt/tmpdisk/b.c
@@ -5,7 +5,7 @@ PHP_FUNCTION(hello_world)
ZVAL_STRING(&p1, "From extension", 1);
zval *params = { &p1 };
zend_uint param_count = 1;
- zval *retval_ptr = NULL;
+ zval retval;
zval function_name;
INIT_ZVAL(function_name);
@@ -13,12 +13,11 @@ PHP_FUNCTION(hello_world)
if (call_user_function(
CG(function_table), NULL /* no object */, &function_name,
- retval_ptr, param_count, ¶ms TSRMLS_CC
+ &retval, param_count, ¶ms TSRMLS_CC
) == SUCCESS
) {
printf("Success returning from PHP");
- if (retval_ptr)
- zval_ptr_dtor(&retval_ptr);
+ zval_dtor(&retval);
}
/* don't forget to free the zvals */
传入一个指向堆栈分配内存的指针是非常好的,因为 PHP 引擎永远不会在调用的任何地方捕获对返回值 zval 的引用(因为返回值在用户空间中是未命名的)。
推荐阅读
- javascript - 使用Javascript将多个图像随机插入不同的表格单元格
- swift - 视频在 WKWebView 的 UIImage 快照中显示为黑框
- azure-cognitive-search - Azure 搜索中的 minimum_should_match 参数
- html - Heroku Deploy 上的图像未显示
- c# - 如何通过 EF Core 对使用标量函数的默认列值进行逆向工程?
- matlab - 在 Simulink Scope 中绘制双重数据
- java - 启动 active-mq 代理后是否可以创建 virtualDestinations 和 compositeQueue?
- javascript - 使用缩放浏览器时如何显示 YouTube 上传日期?
- html - 使用 R 从 tspan 类标签 HTML 中提取文本/数字
- react-native - react native:typeerror null is not an object(评估'_reactnative simdata.default.get sim info().DeviceId0)