前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用C语言扩展PHP功能

用C语言扩展PHP功能

作者头像
Java架构师必看
发布2021-03-22 10:52:10
1.8K0
发布2021-03-22 10:52:10
举报
文章被收录于专栏:Java架构师必看

用C语言扩展PHP功能    PHP经过最近几年的发展已经非常的流行,而且PHP也提供了各种各样非常丰富的函数。 但有时候我们还是需要来扩展PHP。比如:我们自己开发了一个数据库系统,而且有自己的 库函数来操作数据库,这时候,如果想在PHP中来操作我们自己的数据库的话,就必须自己 扩展PHP了,像mysql,postgresql,之所以PHP能够提供这些数据库操作函数,也都是扩展了 PHP的结果。     先看看PHP的源代码结构:     $ cd php-4.4.2/ext     $ ls     会显示出目前该PHP发行版本中所有的扩展模块。     如果想深入学习的话,可以去看看mysql或者postgresql的PHP扩展实现。     下面,我们通过一个简单的模块(mypg)来实现对postgresql的数据库操作。     $ cd php-4.4.2/ext     $ ./ext_skel –extname=mypg     该程序会自动生成mypg目录     $ cd mypg     $ ls     config.m4  CREDITS  EXPERIMENTAL  mypg.c  mypg.php  php_mypg.h  tests     PHP已经自动为我们生成了一些必要的文件和示范代码。     我们需要作一些修改才能正常的编译和使用该mypg模块。     $ vi config.m4     修改成如下内容:

代码语言:javascript
复制

 PHP_ARG_ENABLE(mypg, whether to enable mypg support,
                [  –enable-mypg           Enable mypg support])
if test “$PHP_MYPG” != “no”; then
   dnl Write more examples of tests here…
SEARCH_PATH ; do   dnl     if test -r i/SEARCH_FOR; then   dnl       MYPG_DIR=
  dnl # –with-mypg -> add include path
   dnl PHP_ADD_INCLUDE($MYPG_DIR/include)
  dnl # –with-mypg -> check for lib and symbol presence
   dnl LIBNAME=mypg # you may want to change this
   dnl LIBSYMBOL=mypg # you most likely want to change this
  dnl PHP_CHECK_LIBRARY(LIBNAME,LIBSYMBOL,   dnl [   dnl   PHP_ADD_LIBRARY_WITH_PATH(LIBNAME, MYPG_DIR/lib, MYPG_SHARED_LIBADD)   dnl   AC_DEFINE(HAVE_MYPGLIB,1,[ ])   dnl ],[   dnl   AC_MSG_ERROR([wrong mypg lib version or lib not found])   dnl ],[   dnl   -L
  PHP_NEW_EXTENSION(mypg, mypg.c, $ext_shared)
 fi

dnl开头的为注释,其实我们也只是把某些注释去掉了。

代码语言:javascript
复制
   然后修改php_mypg.h,内容为:
 #ifndef PHP_MYPG_H
 #define PHP_MYPG_H
extern zend_module_entry mypg_module_entry;
 #define phpext_mypg_ptr &mypg_module_entry
#ifdef PHP_WIN32
 #define PHP_MYPG_API __declspec(dllexport)
 #else
 #define PHP_MYPG_API
 #endif
//模块初始化时调用函数
 PHP_MINIT_FUNCTION(mypg);
//我们的数据库连接函数
 PHP_FUNCTION(mypg_connect);
 //我们的数据库操作函数
 PHP_FUNCTION(mypg_execute);
 //我们的数据库关闭函数
 PHP_FUNCTION(mypg_close);
#ifdef ZTS
 #include “TSRM.h”
 #endif
#endif  /* PHP_MYPG_H */   
继续修改mypg.c,内容改为:
 #ifdef HAVE_CONFIG_H
 #include “config.h”
 #endif
#include “php.h”
 #include “php_ini.h”
 #include “ext/standard/info.h”
 #include “php_mypg.h”
 #include “libpq-fe.h”
int le_link;
 function_entry mypg_functions[] = {
         PHP_FE(mypg_connect,                                                    NULL)
         PHP_FE(mypg_execute,                                                    NULL)
         PHP_FE(mypg_close,                                                      NULL)
         {NULL, NULL, NULL}
 };
 zend_module_entry mypg_module_entry = {
         STANDARD_MODULE_HEADER,
         “mypg”, mypg_functions, PHP_MINIT(mypg), NULL, NULL, NULL,
         NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
 };
ZEND_GET_MODULE(mypg)
//数据库链接关闭函数
 static void _close_mypg_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
         PGconn *link = (PGconn *)rsrc->ptr;
         PQfinish(link);
 }
 PHP_MINIT_FUNCTION(mypg)
 {
     //注册资源回收函数,如果没有显示用mypg_close关闭数据库连接的化,PHP会自动调用该函数释放资源
     le_link = zend_register_list_destructors_ex(_close_mypg_link, NULL, “mypg link”, module_number);
     return SUCCESS;
}
//连接数据库
 static void php_mypg_do_connect(INTERNAL_FUNCTION_PARAMETERS)
 {
         PGconn *link;
        //只接受一个函数参数
         if(ZEND_NUM_ARGS() != 1)
         {
             WRONG_PARAM_COUNT;
         }
        zval **connect_info;
        /* get the connection information string */
         if (zend_get_parameters_ex(1, &connect_info) == FAILURE) {
             RETURN_FALSE;
         }
        /* create our resource hash key */
         convert_to_string_ex(connect_info);
        //调用libpq, 执行数据库连接
         if ((link=PQconnectdb(Z_STRVAL_PP(connect_info))) && PQstatus(link)!=CONNECTION_OK) {
             RETURN_FALSE;
         }
 
         //将return_value注册为得到的数据库连接
         /* add it to the list */
         ZEND_REGISTER_RESOURCE(return_value, link, le_link);
 }
 PHP_FUNCTION(mypg_connect)
 {
     php_mypg_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 }
//我们自己定义的数据库操作函数
 PHP_FUNCTION(mypg_execute)
 {
         zval **query, **link = NULL;
         int id;
         PGconn *conn;
         PGresult *res;
        //参数为2, 1:执行的sql  2:数据库链接句柄
         switch(ZEND_NUM_ARGS()) {
                 case 2:
                         if (zend_get_parameters_ex(2, &query, &link)==FAILURE) {
                                 WRONG_PARAM_COUNT;
                         }
                         break;
                 default:
                         WRONG_PARAM_COUNT;
                         break;
         }
 
         //取得数据库链接
         ZEND_FETCH_RESOURCE(conn, PGconn *, link, -1, “mypg link”,  le_link);
        convert_to_string_ex(query);
 
         //通过libpq执行SQL
         res = PQexec(conn, Z_STRVAL_PP(query));
        if (PQresultStatus(res) != PGRES_COMMAND_OK)
         {
                 RETURN_FALSE;
         }
        PQclear(res);
 
         RETURN_TRUE;
}
 PHP_FUNCTION(mypg_close)
 {
         zval **link;
         int id;
         PGconn *conn;
        switch (ZEND_NUM_ARGS()) {
                 case 1:
                         if (zend_get_parameters_ex(1, &link)==FAILURE) {
                                 RETURN_FALSE;
                         }
                         break;
                 default:
                         WRONG_PARAM_COUNT;
                         break;
         }
         if(link == NULL)
         {
                 RETURN_FALSE;
         }
        //根据资源句柄取得资源
         ZEND_FETCH_RESOURCE(conn, PGconn *, link, -1,”mypg link”,  le_link);
 
         //删除该资源,PHP自动调用前面注册的函数来关闭数据库链接
         zend_list_delete(Z_RESVAL_PP(link));
        RETURN_TRUE;
}
     mypg模块就基本开发完成了,我们需要重新为php生成configure文件。
 
     $ cd php-4.4.2
     $ rm -rf autom4te.cache/; rm -f configure
     $ ./buildconf  –force
     此时PHP会读取所有ext/子目录下的config.m4,并集成到新生成的configure脚本中。
     如果没有意外,运行如下命令会得到如下结果:
     $ ./configure –help | grep mypg
       –enable-mypg           Enable mypg support
     编译PHP:
     $ ./configure —enable-mypg
     由于要链接libpq.so,可以vi Makefile
     在EXTRA_LIBS后面加上:-lpq 来把libpq编译进去,当然也可以通过修改mypg的config.m4来实现,
     这里不在啰嗦。
     $ make
     $ make install
 
     编写我们的模块测试脚本:testmypg.php
 /*
 * this is the sample php code
 * to invoke our module: mypg
 */
 $link = mypg_connect(”hostaddr=172.16.19.8 dbname=pgsql user=pgsql password=12345″);
 if($link)
 {
         echo “Successfully connected  to PostgreSQL.\n”;
 }
 else
 {
         die(”Connect error.\n”);
 }
$sql = “insert into test values(’12345′,’23145′)”;
mypg_execute(sql, link);
link2 = link;
mypg_execute(sql, link2); mypg_execute(sql, link); mypg_close(
echo “Database query ok.\n”;
?>
 运行该PHP程序,如果在postgresql的pgsql库中有table: test (col1 varchar(100), col2 varchar(100))
 里面应该已经有2条记录了。

    编写php模块扩展需要很多PHP源码的知识,可以通过参考其他module或者直接阅读PHP代码来逐步提高自己 的开发能力。     php官方的站点上也有一些文章可供参考:http://cn2.php.net/manual/en/internals2.php

http://cn2.php.net/manual/zh/internals2.structure.php     希望这篇文章能够给想扩展PHP的兄弟一个大概的方向!

本文由来源 21aspnet,由 javajgs_com 整理编辑,其版权均为 21aspnet 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档