用C/C++扩展你的PHP 为你的php增加功能(5)


FILE *fopen(const char *path, const char *mode);
int fclose(FILE *stream);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int feof(FILE *stream);



我们实现这些函数,使它们在命名习惯和简单性上符合PHP脚本。如果你曾经向PHP社区贡献过代码,你被期望遵循一些公共习俗,而不是跟随C库里的API。并不是所有的习俗都写在PHP代码树的CODING_STANDARDS文件里。这即是说,此功能已经从PHP发展的很早阶段即被包含在PHP中,并且与C库API类似。PHP安装已经支持fopen(), fclose()和更多的PHP函数。
以下是PHP风格的API:

复制代码 代码如下:


resource file_open(string filename, string mode)
file_open() //接收两个字符串(文件名和模式),返回一个文件的资源句柄。
bool file_close(resource filehandle)
file_close() //接收一个资源句柄,返回真/假指示是否操作成功。
string file_read(resource filehandle, int size)
file_read() //接收一个资源句柄和读入的总字节数,返回读入的字符串。
bool file_write(resource filehandle, string buffer)
file_write() //接收一个资源句柄和被写入的字符串,返回真/假指示是否操作成功。
bool file_eof(resource filehandle)
file_eof() //接收一个资源句柄,返回真/假指示是否到达文件的尾部。



因此,我们的函数定义文件——保存为ext/目录下的myfile.def——内容如下:

复制代码 代码如下:


resource file_open(string filename, string mode)

bool file_close(resource filehandle)

string file_read(resource filehandle, int size)

bool file_write(resource filehandle, string buffer)

bool file_eof(resource filehandle)


下一步,利用ext_skel脚本在ext./ 原代码目录执行下面的命令:

复制代码 代码如下:


./ext_skel --extname=myfile --proto=myfile.de


然后,按照前一个例子的关于编译新建立脚本的步骤操作。你会得到一些包含FETCH_RESOURCE()宏行的编译错误,这样骨架脚本就无法顺利完成编译。为了让骨架扩展顺利通过编译,把那些出错行[3]注释掉即可。

资源
资源是一个能容纳任何信息的抽象数据结构。正如前面提到的,这个信息通常包括例如文件句柄、数据库连接结构和其他一些复杂类型的数据。

使用资源的主要原因是因为:资源被一个集中的队列所管理,该队列可以在PHP开发人员没有在脚本里面显式地释放时可以自动地被释放。

举个例子,考虑到编写一个脚本,在脚本里调用mysql_connect()打开一个MySQL连接,可是当该数据库连接资源不再使用时却没有调用mysql_close()。在PHP里,资源机制能够检测什么时候这个资源应当被释放,然后在当前请求的结尾或通常情况下更早地释放资源。这就为减少内存泄漏赋予了一个“防弹”机制。如果没有这样一个机制,经过几次web请求后,web服务器也许会潜在地泄漏许多内存资源,从而导致服务器当机或出错。

注册资源类型
如何使用资源?Zend引擎让使用资源变地非常容易。你要做的第一件事就是把资源注册到引擎中去。使用这个API函数:

int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number)

这个函数返回一个资源类型id,该id应当被作为全局变量保存在扩展里,以便在必要的时候传递给其他资源API。ld:该资源释放时调用的函数。pld用于在不同请求中始终存在的永久资源,本章不会涉及。type_name是一个具有描述性类型名称的字符串,module_number为引擎内部使用,当我们调用这个函数时,我们只需要传递一个已经定义好的module_number变量。

回到我们的例子中来:我们会添加下面的代码到myfile.c原文件中。该文件包括了资源释放函数的定义,此资源函数被传递给zend_register_list_destructors_ex()注册函数(资源释放函数应该提早添加到文件中,以便在调用zend_register_list_destructors_ex()时该函数已被定义):

复制代码 代码如下:


static void myfile_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC){
FILE *fp = (FILE *) rsrc->ptr;
fclose(fp);
}


把注册行添加到PHP_MINIT_FUNCTION()后,看起来应该如下面的代码:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/613d4dbed6d1c77df2df5be069ee1b62.html