`
hududanyzd
  • 浏览: 786226 次
文章分类
社区版块
存档分类
最新评论

用 SWIG 构建 PHP 扩展

 
阅读更多

作者:Martin Streicher, 软件开发人员, Pixel, Byte, and Comma
尽管编写一个 PHP 扩展并不是很困难,而 SWIG 的确进一步简化了这项任务,这主要是因为它自动化了结合 PHP 与 C 或 C++ 所需的工作。若给定对一个函数的描绘 — 函数的名称及其形参 — SWIG 就会生成一个包装程序来将 PHP 与低层代码连接起来。

SWIG 需要一些前提条件。SWIG 的一些最新版本需要 PHP 的版本是 V5。此外,还需要有一个 C/C++ 编译器,比如 GNU Compiler Collection (GCC),以及 PHP Module Development Kit (MDK)。特别是您还要有与 PHP 安装相关的头文件。如果您使用的是 Ubuntu Linux ® 或一个 Debian 的变体并且已经从一个包存储库安装了 PHP V5,那么一般而言您就可以使用 Advanced Packaging Tool (APT) 添加 MDK 了。例如,在 Ubuntu 内核 9.10 上,键入 apt-get install sudo apt-get install --install-recommends --yes php5-dev。

截止到 2009 年底,SWIG 的最新版本是 V1.3.40(参见 参考资料)。下载 tarball (一个由 gzip 压缩了的 TAR 文件),将它解压缩,然后针对您的系统配置这些代码,构建并安装这个软件。(要想找到所有的配置选项,运行 ./configure --help)。清单 1 提供了下载、解压缩和安装 SWIG 所需的命令。


清单 1. 下载、解压缩和安装 SWIG

$ wget http://prdownloads.sourceforge.net/swig/swig-1.3.40.tar.gz
$ tar xzf swig-1.3.40.tar.gz
$ cd swig-1.3.40
$ ./configure
$ make
$ sudo make install
$ which swig
/usr/local/bin/swig


构建一个扩展

让我们构建一个扩展来用 Linux mcrypt 库加密和解密消息。PHP 提供了一个 mcrypt 库,但它不过是对此库的 C 版本稍作修饰后的结果。现在,让我们构建两个更为简洁的方法:一个用来加密字符串,另一个用来解密字符串。

在 Ubuntu 或与其相似的系统上,您可以用 APT 安装恰当的 mcrypt 库和头文件:$ sudo apt-get install libmcrypt-dev libmcrypt4 mcrypt libmhash2。

若您宁愿从头开始构建,或者您的分布版内不包括 mcrypt,那么可以从它的主页上下载源代码(参见 参考资料)。替代了 crypt 的 mcrypt 实用程序也依赖于 libmhash,因此必须在编译 mcrypt 之前构建 libmhash。清单 2 给出了构建 libmhash 所需的代码。


清单 2. 构建 libmhash

$ # libmhash
$ wget http://sourceforge.net/projects/mhash/files/mhash/0.9.9.9//
mhash-0.9.9.9.tar.bz2/download
$ tar xfj mhash-0.9.9.9.tar.bz2
$ cd mhash-0.9.9.9
$ ./configure
$ make
$ sudo make install

# libmcrypt
$ wget ftp://mcrypt.hellug.gr/pub/crypto/mcrypt/libmcrypt//
libmcrypt-2.5.7.tar.gz
$ tar xfz libmcrypt-2.5.7.tar.gz
$ cd libmcrypt-2.5.7
$ ./configure
$ make
$ sudo make install

$ # mcrypt
$ wget wget http://sourceforge.net/projects/mcrypt/files/MCrypt/2.6.8//
mcrypt-2.6.8.tar.gz/download
$ tar xfz mcrypt-2.6.8.tar.gz
$ cd mcrypt-2.6.8
$ ./configure
$ make
$ sudo make install


接下来,创建此扩展的 C 代码。代码中最有趣的函数是位于 清单 3 底部的 encode() 和 decode()。二者均具有两个形参 — 一个字符串和一个计数 — 并且均返回字符串。前者加密一个纯文本的字符串,返回其编码;后者解密一个加密了的字符串并返回纯文本。字符串可以是任意长度。

上述代码使用了 Data Encryption Standard-Electronic Codebook (DES-ECB) 算法。秘密密匙可以是八个字符的任意字符串,并可显示为 12345678(只用于演示目的)。如果您要与其他方交换加密了的消息,需要获得交换方的密钥或创建一个新的密钥并共享它。(加密算法独立于架构和语言,不过,发送者和接收者均必须知道秘密密匙。)


清单 3. PHP 扩展的 C 代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mcrypt.h>

char *encode( char *string, int length );
char *decode( char *string, int length );

MCRYPT start() {
MCRYPT td = mcrypt_module_open( "des", NULL, "ecb", NULL );
if ( td == MCRYPT_FAILED ) {
return( MCRYPT_FAILED );
}

if ( mcrypt_enc_self_test( td ) != 0 ) {
return( MCRYPT_FAILED );
}

int i;
char *IV;
int iv_size = mcrypt_enc_get_iv_size( td );
if ( iv_size != 0 ) {
IV = calloc( 1, iv_size );
for ( i = 0; i < iv_size; i++ ) {
IV[ i ] = rand();
}
}

int keysize = mcrypt_enc_get_key_size( td );
char *key = calloc( 1, keysize );
memcpy(key, "12345678", keysize);

i = mcrypt_generic_init ( td, key, keysize, IV );
if ( i < 0 ) {
mcrypt_perror( i );
exit(1);
}

return( td );
}


void end( MCRYPT td ) {
mcrypt_generic_deinit( td );
mcrypt_module_close( td );
}


#define B64_DEF_LINE_SIZE 72
#define B64_MIN_LINE_SIZE 4

/*
** encode 3 8-bit binary bytes as 4 '6-bit' characters
*/
void encodeblock( unsigned char in[3], unsigned char out[4], int len ) {
static const char
cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
out[0] = cb64[ in[0] >> 2 ];
out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? cb64[
((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}


char *base64encode( char *input, int size ) {
int i, x, len;
unsigned char in[3], out[4];
char *target = calloc( 1, ( ( size + 2 ) / 3 ) * 4 + 1 );
char *t = target;

for ( x = 0; x < size; ) {
len = 0;

for( i = 0; i < 3; i++ ) {
if ( x < size ) {
len++;
in[i] = input[x++];
}
else {
in[i] = 0;
}
}

if( len ) {
encodeblock( in, out, len );
for( i = 0; i < 4; i++ ) {
*t++ = out[i];
}
}
}

return( target );
}


char *encode( char *string, int length ) {
MCRYPT td = start();
int blocksize = mcrypt_enc_get_block_size( td );
int cryptsize = ( ( length + blocksize - 1 ) / blocksize ) * blocksize;
char *target = calloc( 1, cryptsize );

memcpy( target, string, length );

if ( mcrypt_generic( td, target, cryptsize ) != 0 ) {
fprintf( stderr, "Code failing" );
}

end( td );

char* result = base64encode( target, cryptsize );

free( target );
return result;
}


char *decode( char *string, int length ) {
MCRYPT td = start();
int blocksize = mcrypt_enc_get_block_size( td );
char *block_buffer = calloc( 1, blocksize );
int decryptlength = (length + blocksize - 1) / blocksize * blocksize;
char *target = calloc( 1, decryptlength );

memcpy(target, string, length);

mdecrypt_generic( td, target, decryptlength );

end( td );

free(block_buffer);
return( target );
}


将清单 3 内的代码复制并粘贴到一个名为 secret.c 的新文件。下一个任务是使用 SWIG 自身的语法描述此扩展的 API。


--------------------------------------------------------------------------------

回页首

SWIG 文件

在目前的开发阶段,可以在 secret.c 基础上手动构建一个扩展。但 SWIG 可以帮您完成这一艰苦工作 — 并且只需采用少量的伪代码。清单 4 所示的 secret.i 就是这个新扩展的 SWIG 模板。


清单 4. secret.i

%module secret

%{
extern char *encode( char *string, int length );
extern char *decode( char *string, int length );
%}

extern char *encode( char *string, int length );
extern char *decode( char *string, int length );


对 SWIG 语法和选项的全面解读超出了本文的讨论范围。完整的文档,可以在网上找到(参见 参考资料)。简单来讲,SWIG 文件一般在第 1 行声明扩展的名称。文件的其他部分声明入口点。就是这些内容。编译需要几个步骤:第一步是生成代码的包装程序:$ swig -php secret.i。

SWIG 将 secret.i 转变为 secret_wrap.c。接下来的几个步骤是构建和链接这些包装程序代码、这个扩展以及 mcrypt 库。请务必用 -fpic 选项构建每个 C 源文件,因该选项可以生成独立于位置的代码,这非常适合于共享库。

$ cc -fpic -c secret.c
$ gcc `php-config --includes` -fpic -c secret_wrap.c
$ gcc -shared *.o -o secret.so -lmcrypt
$ sudo cp secret.so `php-config --extension-dir`


前两个命令构建 C 源代码。第三个命令构建 PHP 扩展。-lmcrypt 选项解析此扩展内入口点在 mcrypt 库内的那些调用。第四个命令会将这个新的 PHP 扩展放入合适的目录以便它可被 PHP 加载。

在开始编写 PHP 代码之前,最后一步是加载这个扩展。打开适当的 php.ini 文件 — 或者针对 Apache,或者针对 PHP 的命令行变体 — 并添加一行代码:extension=secret.so。

如果不确定该编辑哪个 php.ini 文件,可以查询 PHP 本身。创建如下所示的这个共三行代码的程序并使用浏览器或交互解释器运行它:

<?php
phpinfo();
?>


查找以 Loaded Configuration File 开头的一行代码。例如,在本文使用的测试平台上,此程序生成了输出 Loaded Configuration File => /etc/php5/cli/php.ini。因此,要编辑的文件是 /etc/php5/cli/php.ini。


--------------------------------------------------------------------------------

回页首

编写 PHP 代码

有了这个出色的新扩展后,就可以开始编写 PHP 了。清单 5 显示了 code.php。


清单 5. code.php

<?php
include("secret.php");

$string = "Double secret probation";
$base64encode = secret::encode($string, strlen($string));
$base64decode = base64_decode($base64encode);
$decode = secret::decode( $base64decode, strlen($base64decode));

echo $decode . "/n";
?>


行 1 加载此扩展。行 4 编码字符串 Double secret probation 并使用 Base64 将加密了的这个字符串转变为可打印的字符,以便于用电子邮件等程序传输。行 5 对 Base64 编码进行解码以生成原始字符,行 6 将加密消息解密成原始文本。

假设将这些代码保存在 coder.php 内,并在系统的 /usr/local/lib 下安装了 mcrypt 库,用 PHP CLI 命令就可以运行这些示例代码了:

$ LD_LIBRARY_PATH=/usr/local/lib php ./code.php
Double secret probation

--------------------------------------------------------------------------------

回页首

结束语

SWIG 是重用现有代码的一种极好的方式。用 SWIG 包装 C 或 C++ 库,并将结果集成到您的下一个 Web 或系统应用程序。而更妙的是,SWIG 还可以从相同的 .i 文件生成面向其他脚本语言的包装程序。您只需编写一次扩展,之后,就可以与 PHP、Perl、Python、Ruby 和其他开发人员共享它了。


参考资料

学习

在 SWIG 站点了解有关 SWIG 扩展生成器的更多信息。

查阅 SWIG 文档,获得可以使 SWIG 变得更易使用的文章和教程。此项目还维护着几个 wikis。

PHP.net 是 PHP 开发人员资源中心。

查看 “推荐 PHP 读物列表”。

浏览 developerWorks 上的所有 PHP 内容。

查看 IBM developerWorks 的 PHP 项目资源,扩展 PHP 技能。

要收听面向软件开发人员的有趣访谈和讨论,请访问 developerWorks podcasts。

在 PHP 中使用数据库?试试 Zend Core for IBM,这是一个无缝、即开即用、易于安装的 PHP 开发和生产环境,支持 IBM DB2 V9。

My developerWorks 社区是一个成功社区的典范,涵盖了各种内容的主题。

随时关注 developerWorks 技术活动和网络广播。

查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、交易展览、网络广播和其他 活动。

访问 developerWorks Open source 专区 获得丰富的 how-to 信息、工具和项目更新以及 最受欢迎的文章和教程,帮助您用开放源码技术进行开发,并将它们与 IBM 产品结合使用。

查看免费的 developerWorks 演示中心,观看并了解 IBM 及开源技术和产品功能。

获得产品和技术

从这个项目站点 下载 SWIG。

下载 mcrypt 库的源代码。

使用 IBM 产品评估试用版软件 改进您的下一个开源开发项目,这些软件可以通过下载获得。

下载 IBM 产品评估试用版软件 或 IBM SOA Sandbox for Reuse,并使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。

讨论

参与 developerWorks blogs 并加入 developerWorks 社区。

参与 developerWorks PHP 论坛:用 IBM 信息管理产品(DB2、IDS)开发 PHP 应用程序。
来源:http://www.ibm.com/developerworks/cn/opensource/os-php-swig/index.html

出处:http://blog.csdn.net/heiyeshuwu/archive/2010/03/02/5338344.aspx

分享到:
评论

相关推荐

    node+express+mongodb+swig 构建blog 系统.zip

    基于node js、vue、mongodb等技术构建的web系统,界面美观,功能齐全,适合用作毕业设计、课程设计作业等,项目均经过测试,可快速部署运行! 基于node js、vue、mongodb等技术构建的web系统,界面美观,功能齐全,...

    Ruby中使用SWIG编写ruby扩展模块实例

    在使用ruby/rails的过程中,确实发现有时性能不尽人意,如生成一个拥有600项的item的3层树形结构目录要花去20ms,为提高性能在学习用c/c++写ruby模块的过程中,认识了swig,rubyInline等一系列帮助编写c/c++来提升...

    使用Swig转换C++库到C#示例代码

    使用Swig转换C++库到C#示例代码, 包含了示例的动态库和对应的代码 打包了应用程序 示例用法,提供参考

    swig工具,C/C++到python, tcl 的接口

    * 非侵入式接口构建:SWIG可以生成非侵入式的接口,无需修改原始代码。 * 自由代码生成:SWIG可以自动生成wrapper代码,提高开发效率。 * 可以与build系统集成:SWIG可以与build系统集成,自动生成wrapper代码。 ...

    SWIG-4.0.2 for windows swig.exe

    SWIG-4.0.2官方版本,由于有时官网上不了,放在这里方便使用 SWIG Version 4.0.2 Compiled with i686-w64-mingw32-g++ [i686-w64-mingw32] Configured options: +pcre

    swig使用手册

    swig使用手册,swig使用必备必备

    SWIG源码及工具

    SWIG工具

    SWIG简明使用说明系列

    本文档深入浅出的说明了SWIG的使用,通过该例子读者能够快速入门SWIG。

    swig-4.0.2-windows版本安装包

    swig-4.0.2-windows版本安装包

    SWIG 源码(C/C++与其他语言的粘合剂)

    SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby and PHP。支持语言列表中也包括非脚本...

    android ndk swig例子

    android ndk swig例子。

    android studio 使用NDK和swig编译c++示例

    android studio 使用NDK和swig编译c++示例。使用swig可以自动化编译c++函数。比较方便。http://blog.csdn.net/qq_16064871

    SWIG英文说明书

    SWIG英文说明书

    android swig编译工具下载

    android swig编译工具下载,关于android studio 使用swig相关网站:http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/;swig的官方下载:http://www.swig.org/download.html;我的博客...

    前端开源库-koa-swig

    前端开源库-koa-swigKoa Swig、基于Swig的Koa视图渲染、支持标记、过滤器和扩展。

    swig 打包C++ python应用

    swig 打包C/C++程序;供python调用。 本软件操作平台windows 10 Vs2017;python3.8; 主要讲述swig vs配置,测试用例。 主要包含常量,变量,指针,结构体定义及运用。

    cygwin+swig生成Android库并使用的例子

    cygwin+swig生成Android库并使用的例子 C/C++转变为Android使用的接口

    perl-extensions:使用 SWIG 编写 perl C 扩展

    我已经使用 SWIG(以两种机制)和 perlguts 构建了包装器。 这是我之前完成的 python swig 项目的 perl 等价物。 要构建和安装所有 perl 扩展: make -f Makefile.main 这将生成 swig 包装器文件并编译扩展。 ...

    SWIG4.0开发手册

    SWIG软件开发工具,适用于将C\C++转换成C#、python等高级语言

    swig-1.3.40 for windows

    swig for windows 最新1.3.40版本

Global site tag (gtag.js) - Google Analytics