mysql c语言扩展_用C语言扩展PHP功能

用C语言扩展PHP功能建议读者群:熟悉c,linux,php  PHP经过最近几年的发展已经非常的PHP

用C语言扩展PHP功能

建议读者群:熟悉c,linux,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

修改成如下内容:

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…

dnl # –with-mypg -> check with-path

dnl SEARCH_PATH=”/usr/local /usr”     # you might want to change this

dnl SEARCH_FOR=”/include/mypg.h”  # you most likely want to change this

dnl if test -r $PHP_MYPG/; then # path given as parameter

dnl   MYPG_DIR=$PHP_MYPG

dnl else # search default path list

dnl   AC_MSG_CHECKING([for mypg files in default path])

dnl   for i in $SEARCH_PATH ; do

dnl     if test -r $i/$SEARCH_FOR; then

dnl       MYPG_DIR=$i

dnl       AC_MSG_RESULT(found in $i)

dnl     fi

dnl   done

dnl fi

dnl

dnl if test -z “$MYPG_DIR”; then

dnl   AC_MSG_RESULT([not found])

dnl   AC_MSG_ERROR([Please reinstall the mypg distribution])

dnl fi

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$MYPG_DIR/lib -lm -ldl

dnl ])

dnl

dnl PHP_SUBST(MYPG_SHARED_LIBADD)

PHP_NEW_EXTENSION(mypg, mypg.c, $ext_shared)

fi

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

然后修改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($link);

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值