PHP 扩展好的资源不多, 转的这个朋友应该是个高手他在实践中摸索出来的这些经验和大家分享
红色部分是我的注释
更多信息参看:
1. 常用的通用功能已经封装好了, 在如 zen_API.h 头文件中, 不用费力查看内部细节, 浪费时间(参考: Extending and Embedding PHP 的附录 A)
2. 在 terminal 中运行测试程序, 可以看到扩展的内部错误输出, 这一点对于解决内存泄漏问题尤其重要(编译一个 debug 的 lib)
3. 开发过程中修改 Makefile 中的 CFLAGS = -g -O2, 去掉优化选项, 增加 - Wall 和 - pedantic, 便于调试和显示编译警告;
4. 某 zval*, 但其 strval 非拷贝的, 不可用 zval_ptr_dtor(zval**), 要用 efree(void*)
5.terminal 中的 $_SERVER['PWD']有值, 但是无法通过 zend_getenv()取得, 原因应该是该值无意义或不可靠
6. 调用导出函数, 可利用 INTERNAL_FUNCTION_PARAM_PASSTHRU 传参; 声明的非导出函数可通过 INTERNAL_FUNCTION_PARAM 使用导出函数的参数
7. 注意: RETURN_TYPE 用在选择分之和循环等处时, 最好置于花括号中,
或者不用分号, 因为:#define RETURN_BOOL(b) { RETVAL_BOOL(b); return; }
8. 如果函数的参数是引用的, 且非标量, 要先析构, 以防内存泄露
9. 抛出异常前最好判断 EG(exception)中是否已经存在异常, 否则会造成内存泄露
10. 当 web 服务器 API 是 ISAPI (IIS)的时候, zend_getenv 函数是不起作用的
11. 向 zend_stack_push()传入数据指针, 实际存储 (copy) 的是该指针指向的数据, 换句话说, 传入的应该是要存储的数据的指针
- ZEND_API int zend_stack_push(zend_stack *stack, void *element, int size);
- ZEND_API int zend_stack_top(zend_stack *stack, void **element);
其中, size == sizeof(*element);
类似地, zend_hash 也是如此, 比较 zend_hash_update 和 zend_hash_find
12. 使用 add_assoc_zval(HashTable*, const char*, zval*)存储的是 zval*, 而非 zval, 因此,
存储用户传入的参数时候, 要先拷贝一份新的 zval, 否则会发生不可预料的事情
13.zval_dtor(zval*)释放变量及其内部的引用内存, zval_ptr_dtor(zval**)先检查 refcount
再决定是否调用 zval_dtor(zval*),zval_copy_dtor(zval*)仅执行深层的拷贝, 即只拷贝
起内部引用的内存, 而不拷贝 zval;
14. 如使用 VC 编译 win 的动态链接库, 而且代码中调用了 zend 函数, 如 zend_getenv, 在 zend.h 中定义为:
- extern "C" {
- extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
- }
需要引入该函数, 如要使用 ZEND_API, 需要事先取消 LIBZEND_EXPORTS(包括 VC 设置中的预处理定义), 或者使用 ZEND_DLIMPORT,
ZEND_DLIMPORT char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
下面取自: zend_config.w32.h
代码如下:
- #ifdef LIBZEND_EXPORTS
- # define ZEND_API __declspec(dllexport)
- #else
- # define ZEND_API __declspec(dllimport)
- #endif
- #define ZEND_DLEXPORT __declspec(dllexport)
- #define ZEND_DLIMPORT __declspec(dllimport)
executor_globals_id 也需要作如下声明:
- ZEND_DLIMPORT int executor_globals_id;
- (这个比较有用, 如果你要手工编译某些扩展的时候, 比如我在编译 sqlite3 这个扩展的时候, 就遇到这个问题)
来源: https://www.php1.cn/detail/php-4883bb53c4.html