php怎么运行c语言程序?利用php调用C语言 扩展PHP的功能

C或PHP中的Rust

我的基本出发点就是写一些可以编译的Rust代码到一个库里面,并写为它一些C的头文件,在C中为被调用的PHP做一个拓展。虽然并不是很简单,但是很有趣。

$ su        // 切换成超级用户,此时,需要输入密码。

PHP_HELLO_VERSION是扩展的版本号,定义在头文件中

总结

这里几乎没有得出什么结论。我不确定在Rust上写一个PHP的扩展是一个好的想法,但是花费一些时间去研究Rust,PHP和C,这是一个很好的方式。

如果你希望查看所有代码或者查看更改记录,可以访问GitHub
Repo。

<?php

如果你的扩展用到了外部依赖,就配置–with-hello选项,否则配置–enable-hello选项,删除这下面3行的del注释

Rust FFI(foreign function interface)

我所做的第一件事情就是摆弄Rust与C连接的Rust的外部函数接口。我曾用简单的方法(hello_from_rust)写过一个灵活的库,伴有单一的声明(a
pointer to a C char, otherwise known as a
string),如下是输入后输出的“Hello
from Rust”。

// hello_from_rust.rs
#![crate_type = "staticlib"]

#![feature(libc)]
extern crate libc;
use std::ffi::CStr;

#[no_mangle]
pub extern "C" fn hello_from_rust(name: *const libc::c_char) {
    let buf_name = unsafe { CStr::from_ptr(name).to_bytes() };
    let str_name = String::from_utf8(buf_name.to_vec()).unwrap();
    let c_name   = format!("Hello from Rust, {}", str_name);
    println!("{}", c_name);
}

我从C(或其它!)中调用的Rust库拆分它。这有一个接下来会怎样的很好的解释。

编译它会得到.a的一个文件,libhello_from_rust.a。这是一个静态的库,包含它自己所有的依赖关系,而且我们在编译一个C程序的时候链接它,这让我们能做后续的事情。注意:在我们编译后会得到如下输出:

note: link against the following native artifacts when linking against this static library
note: the order and any duplication can be significant on some platforms, and so may need to be preserved
note: library: Systemnote: library: pthread
note: library: c
note: library: m

这就是Rust编译器在我们不使用这个依赖的时候所告诉我们需要链接什么。

2.
执行该命令之后它会提示你应当用什么命令来编译模块,可惜那是将模块集成到php内部的编译方法。

hello_functions是扩展包含的全部方法的集合

从那时起我便萌生了用Rust写一个的想法,过去的几天一直在尝试。今天上午我终于让它运行了。

dnl Make sure that the comment is aligned:

好了,到这一步我们终于要开始写代码了,打开hello.c文件。

无用的微基准

那么为什么你还要这样做?我还真的没有在现实世界里使用过这个。但是我真的认为斐波那契序列算法就是一个好的例子来说明一个PHP拓展如何很基本。通常是直截了当(在Ruby中):

def fib(at) do
    if (at == 1 || at == 0)
        return at
    else
        return fib(at - 1) + fib(at - 2)
    end
end

而且可以通过不使用递归来改善这不好的性能:

def fib(at) do
    if (at == 1 || at == 0)
        return at
    elsif (val = @cache[at]).present?
        return val  
    end

    total  = 1
    parent = 1
    gp     = 1

    (1..at).each do |i|
        total  = parent + gp
        gp     = parent
        parent = total
    end

    return total
end

那么我们围绕它来写两个例子,一个在PHP中,一个在Rust中。看看哪个更快。下面是PHP版:

def fib(at) do
    if (at == 1 || at == 0)
        return at
    elsif (val = @cache[at]).present?
        return val  
    end

    total  = 1
    parent = 1
    gp     = 1

    (1..at).each do |i|
        total  = parent + gp
        gp     = parent
        parent = total
    end

    return total
end

这是它的运行结果:

$ time php php_fib.php

real    0m2.046s
user    0m1.823s
sys 0m0.207s

现在我们来做Rust版。下面是库资源:

#![crate_type = "staticlib"]

fn fib(at: usize) -> usize {
    if at == 0 {
        return 0;
    } else if at == 1 {
        return 1;
    }

    let mut total  = 1;
    let mut parent = 1;
    let mut gp     = 0;
    for _ in 1 .. at {
        total  = parent + gp;
        gp     = parent;
        parent = total;
    }

    return total;
}

#[no_mangle]
pub extern "C" fn rust_fib(at: usize) -> usize {
    fib(at)
}

注意,我编译的库rustc – O
rust_lib.rs使编译器优化(因为我们是这里的标准)。这里是C扩展源(相关摘录):

PHP_FUNCTION(confirm_rust_fib_compiled)
{
    long number;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &number) == FAILURE) {
        return;
    }

    RETURN_LONG(rust_fib(number));
}

运行PHP脚本:

<?php
$br = (php_sapi_name() == "cli")? "":"<br>";

if(!extension_loaded('rust_fib')) {
    dl('rust_fib.' . PHP_SHLIB_SUFFIX);
}

for ($i = 0; $i < 100000; $i ++) {
    confirm_rust_fib_compiled(92);
}
?>

这就是它的运行结果:

$ time php rust_fib.php

real    0m0.586s
user    0m0.342s
sys 0m0.221s

你可以看见它比前者快了三倍!完美的Rust微基准!

Installing shared extensions:     /usr/lib/php5/20060613+lfs/$ su# cp
modules/hello.so/usr/lib/php/modules

extension = hello.so

去年十月,我和 Etsy
的同事有过一个关于如何为像PHP样的解释性语言写拓展的讨论,Ruby或Python目前的状况应该会比PHP容易。我们谈到了写一个成功创建扩展的障碍是它们通常需要用C来写,但是如果你不擅长C这门语言的话很难有那个信心。

$ gcc -O -c -fPIC -o hello.o hello.c                      //
-fPIC:是指生成的动态库与位置无关

类似于C语音的头文件,包含了一些自定义的结构和函数声明,在这个demo中暂时不需要改动

从C中调用Rust

既然我们有了一个库,不得不做两件事来保证它从C中可调用。首先,我们需要为它创建一个C的头文件,hello_from_rust.h。然后在我们编译的时候链接到它。

下面是头文件:

// hello_from_rust.h
#ifndef __HELLO
#define __HELLO

void hello_from_rust(const char *name);

#endif

这是一个相当基础的头文件,仅仅为了一个简单的函数提供签名/定义。接着我们需要写一个C程序并使用它。

// hello.c
#include <stdio.h>
#include <stdlib.h>
#include "hello_from_rust.h"

int main(int argc, char *argv[]) {
    hello_from_rust("Jared!");
}

我们通过运行一下代码来编译它:

gcc -Wall -o hello_c hello.c -L /Users/jmcfarland/code/rust/php-hello-rust -lhello_from_rust -lSystem -lpthread -lc -lm

注意在末尾的-lSystem -lpthread -lc -lm告诉gcc不要链接那些“本地的古董”,为了当编译我们的Rust库时Rust编译器可以提供出来。

经运行下面的代码我们可以得到一个二进制的文件:

$ ./hello_c
Hello from Rust, Jared!

漂亮!我们刚才从C中调用了Rust库。现在我们需要理解Rust库是如何进入一个PHP扩展的。

从 php 中调用 c

该部分花了我一些时间来弄明白,在这个世界上,该文档在 php
扩展中并不是最好的。最好的部分是来自绑定一个脚本 ext_skel 的 php
源(大多数代表“扩展骨架”)即生成大多数你需要的样板代码。为了让代码运行,我十分努力地学习
php
文档,“扩展骨骼”。

你可以通过下载来开始,和未配额的 php 源,把代码写进 php 目录并且运行:

$ cd ext/
$ ./ext_skel –extname=hello_from_rust

这将生成需要创建 php
扩展的基本骨架。现在,移动你处处想局部地保持你的扩展的文件夹。并且移动你的

.rust 源

.rust库

.c header

进入同一个目录。因此,现在你应该看看像这样的一个目录:

.
├── CREDITS
├── EXPERIMENTAL
├── config.m4
├── config.w32
├── hello_from_rust.c
├── hello_from_rust.h
├── hello_from_rust.php
├── hello_from_rust.rs
├── libhello_from_rust.a
├── php_hello_from_rust.h
└── tests
└── 001.phpt

一个目录,11个文件

你可以在 php docs
在上面看到关于这些文件很好的描述。建立一个扩展的文件。我们将通过编辑
config.m4 来开始吧。

不解释,下面就是我的成果:

PHP_ARG_WITH(hello_from_rust, for hello_from_rust support,
[  --with-hello_from_rust             Include hello_from_rust support])

if test "$PHP_HELLO_FROM_RUST" != "no"; then
  PHP_SUBST(HELLO_FROM_RUST_SHARED_LIBADD)

  PHP_ADD_LIBRARY_WITH_PATH(hello_from_rust, ., HELLO_FROM_RUST_SHARED_LIBADD)

  PHP_NEW_EXTENSION(hello_from_rust, hello_from_rust.c, $ext_shared)
fi

正如我所理解的那样,这些是基本的宏命令。但是有关这些宏命令的文档是相当糟糕的(比如:google”PHP_ADD_LIBRARY_WITH_PATH”并没有出现PHP团队所写的结果)。我偶然这个PHP_ADD_LIBRARY_PATH宏命令在有些人所谈论的在一个PHP拓展里链接一个静态库的先前的线程里。在评论中其它的推荐使用的宏命令是在我运行ext_skel后产生的。

既然我们进行了配置设置,我们需要从PHP脚本中实际地调用库。为此我们得修改自动生成的文件,hello_from_rust.c。首先我们添加hello_from_rust.h头文件到包含命令中。然后我们要修改confirm_hello_from_rust_compiled的定义方法。

#include "hello_from_rust.h"

// a bunch of comments and code removed...

PHP_FUNCTION(confirm_hello_from_rust_compiled)
{
    char *arg = NULL;
    int arg_len, len;
    char *strg;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
        return;
    }

    hello_from_rust("Jared (from PHP!!)!");

    len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "hello_from_rust", arg);
    RETURN_STRINGL(strg, len, 0);
}

注意:我添加了hello_from_rust(“Jared (fromPHP!!)!”);。

现在,我们可以试着建立我们的扩展:

$ phpize
$ ./configure
$ sudo make install

就是它,生成我们的元配置,运行生成的配置命令,然后安装该扩展。安装时,我必须亲自使用sudo,因为我的用户并不拥有安装目录的
php 扩展。

现在,我们可以运行它啦!

$ php hello_from_rust.php
Functions available in the test extension:
confirm_hello_from_rust_compiled

Hello from Rust, Jared (from PHP!!)!
Congratulations! You have successfully modified ext/hello_from_rust/config.m4. Module hello_from_rust is now compiled into PHP.
Segmentation fault: 11

还不错,php 已进入我们的 c 扩展,看到我们的应用方法列表并且调用。接着,c
扩展已进入我们的 rust
库,开始打印我们的字符串。那很有趣!但是……那段错误的结局发生了什么?

 

正如我所提到的,这里是使用了 Rust 相关的 println!
宏,但是我没有对它做进一步的调试。如果我们从我们的 Rust
库中删除并返回一个 char* 替代,段错误就会消失。

这里是 Rust 的代码:

#![crate_type = "staticlib"]

#![feature(libc)]
extern crate libc;
use std::ffi::{CStr, CString};

#[no_mangle]
pub extern "C" fn hello_from_rust(name: *const libc::c_char) -> *const libc::c_char {
    let buf_name = unsafe { CStr::from_ptr(name).to_bytes() };
    let str_name = String::from_utf8(buf_name.to_vec()).unwrap();
    let c_name   = format!("Hello from Rust, {}", str_name);

    CString::new(c_name).unwrap().as_ptr()
}

并变更 C 头文件:

#ifndef __HELLO
#define __HELLO

const char * hello_from_rust(const char *name);

#endif

还要变更 C 扩展文件:

PHP_FUNCTION(confirm_hello_from_rust_compiled)
{
    char *arg = NULL;
    int arg_len, len;
    char *strg;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
        return;
    }

    char *str;
    str = hello_from_rust("Jared (from PHP!!)!");
    printf("%s/n", str);

    len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "hello_from_rust", arg);
    RETURN_STRINGL(strg, len, 0);
}

function_entry my_module_functions[] = {

后面5个宏分别代表5个扩展特定方法

更新: 初稿刚发布还没几个小时我意识到我的 PHP
基准测试是错的。为公平起见我已经更新了 PHP 和 Rust 的版本。你可以在
GitHub 仓库里看到変更(链接在底部)。

另外可以在apache重启的时候让我们的so库直接动态编译进php5,就像linux的insmod
hello.ko模块一样,不用dl加载也不用重新编译php,就可以直接使用so的函数了,步骤如下:

解压源码压缩包, tar xzf
php-7.0.2.tar.gz,我们现在只需要关注Zend和ext这两个目录。

    echo hello_add(3, 4);

“hello”是扩展的名字

dnl Make sure that the comment is aligned:

开发PHP扩展,在写C代码之前,要先配置一下这里。我们打开可以看到详细的注释说明,dnl是注释语法。

    printf(“%d + %d = %d”, a, b, hello_add(a,b));

./configuremakemake install

  dnl Write more examples of tests here…

真正的逻辑代码都在这个文件中,后面会详细介绍。

if test “$PHP_MY_MODULE” != “no”; then

ext目录里面包含了PHP原生的扩展,以及我们开发自己的扩展时可以利用的工具,Linux下使用ext_skel,Windows下使用ext_skel_win32.php

1.  $ cd ..
2.  $ vi ext/jinzhesheng_module/config.m4
3.  $ ./buildconf
4.  $ ./configure –[with|enable]-jinzhesheng_module
5.  $ make
6.  $ ./php -f ext/jinzhesheng_module/jinzhesheng_module.php
7.  $ vi ext/jinzhesheng_module/jinzhesheng_module.c
8.  $ make
执行了这个步骤以后你会看到这样的结果
Repeat steps 3-6 until you are satisfied with
ext/jinzhesheng_module/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start
writing
code and repeat the last two steps as often as necessary.
这样以后我们会在这个目录下生成一个目录叫jinzhesheng_module
进入这里面我们看看
[root@ns ext]# cd jinzhesheng_module/
[root@ns jinzhesheng_module]# ls
config.m4  EXPERIMENTAL          jinzhesheng_module.php    tests
CREDITS    jinzhesheng_module.c  php_jinzhesheng_module.h

zend_module_entry hello_module_entry = { STANDARD_MODULE_HEADER, "hello", hello_functions, PHP_MINIT, PHP_MSHUTDOWN, PHP_RINIT, /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN, /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO, PHP_HELLO_VERSION, STANDARD_MODULE_PROPERTIES};
  1. 写段小程序来验证其正确性:

一、下载PHP源代码

第三步. 制作PHP模块(内部模块)

PHP_FUNCTION{ php_printf; RETURN_TRUE;}

    return 0;

本文实例讲述了PHP7扩展开发教程之Hello
World实现方法。分享给大家供大家参考,具体如下:

PHP_FUNCTION(confirm_hello_compiled);   /* For testing, remove
later. */

整个扩展的入口是zend_module_entry这个结构,具体的定义可以在Zend目录下的zend_modules.h文件中看到,一共有十几个属性,快速跳过,我们暂时只需要”hello
world”。

* To compile, use following commands:

写一个test.php方法,执行脚本就可以看到”Hello World!”

  1. $ ./configure

我下载了PHP-7.0.2,地址是:

dnl PHP_ARG_ENABLE(my_module, whether to enable my_module support,

Zend目录里面包含了PHP的Zend
Engine源代码,有些函数和宏的定义我们需要在这里面简单地看一下。

 *   gcc -O -c -fPIC -o hello.o hello.c

最后就是编译安装我们的扩展了,安装过PHP扩展的同学不用看,没有经验的可以参考一下。

    return a + b;

配置好的内容,在后面执行configure --help时可以看到。

        {NULL, NULL, NULL}      /* Must be the last line in
my_module_functions[] */

ext目录下多了一个hello目录,我们后续的工作都在这个目录下面,工具已经为我们自动生成了一些文件。

}

hello.c代码文件

不能reload而必须restart apache,这样so就像insmod
hello.ko一样被融到了php5内核,然后代码就可以忽略掉dl(“hello.so”);了,

先在扩展的方法数组中添加上hello_world,然后再定义hello_world。找到confirm_hello_compiled方法定义的地方,在它下面依葫芦画瓢,php_printf是Zend
Engine中的printf方法。

然后将它编译成.so文件并放到系统中:

./ext_skel --extname=hello

    int a = 3, b = 4;

现在PHP的扩展目录中已经有了hello.so这个文件,在php.ini中添加上扩展的配置

  dnl following line and you are ready to go.

config.m4配置文件

$ gcc -o hellotest -lhello hellotest.c                //
编译测试文件,生成测试程序

PHP_ARG_ENABLE(hello, whether to enable hello support,Make sure that the comment is aligned:[ --enable-hello Enable hello support])

代码如下:

PHP_ARG_WITH和PHP_ARG_ENABLE这两个宏用来配置configure选项,一个配置需要外部依赖的,另一个配置不需要外部依赖的

修改成

打开随便看一下,不算太复杂,但是自己写一个类似的还是挺头疼的,这时就需要用到我前面提到的ext_skel工具了。这个工具也在ext目录下,我们执行一下,./ext_skel
–help,可以看到若干参数,我们用到的只有–extname=module,这里填上自己开发的扩展名称。想深入了解各个参数的作用可以看这里:

dnl Comments in this file start with the string ‘dnl’.

STANDARD_MODULE_PROPERTIES帮我们实现了剩下的属性

编译并执行:

更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP扩展开发教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》、《PHP网络编程技巧总结》及《php常见数据库操作技巧汇总》希望本文所述对大家PHP程序设计有所帮助。

        PHP_FE(confirm_my_module_compiled,      NULL) /* For
testing, remove later. */

三、编写代码

17:  dnl Make sure that the comment is aligned:

要开发PHP扩展,需要先下载PHP的源代码,一方面是因为我们的扩展一般会用到PHP自身定义的函数和宏,另一方面我们可以利用官方提供的工具减少工作量。

dnl [  –with-my_module             Include my_module support])

二、使用ext_skel工具

PHP_ARG_ENABLE(my_module, whether to enable my_module support,

五、测试

enable_dl = Off;允许dl()动态加载so扩展功能enable_dl = On

php_hello.h头文件

dnl Otherwise use enable:

暂时都不需要修改,知道这是一个入口就行。顺着这个入口,我们继续看怎么给扩展添加方法,在hello_functions[]方法数组中已经有了一个示例方法confirm_hello_compiled,我们参考它写我们的方法hello_world

        return;

我们可以在ext目录下看到所有的PHP原生扩展,其中包括了熟悉的curl,json,mbstring,simplexml,sockets等扩展,还有很多没有用过甚至没有听说过的扩展,不用在意这些,我们先打开我们最熟悉的curl来看看,有config.m4配置文件,有php_curl.h,curl_file.c等源代码,还有一些中间文件,最后还有一个tests目录,里面放的curl扩展的单元测试。重点关注config.m4,php_curl.h,curl_file.c即可,最简单的场景下这三个文件就是一个扩展的全部组成部分了。

        PHP_FE(say_hello,       NULL)  /* ?添加着一行代码 */

STANDARD_MODULE_HEADER帮我们实现了前面6个属性

然后在浏览器中打开hello.php文件,如果显示7,则说明函数调用成功了。

四、编译安装

    PHP_FE(hello_add,   NULL)       /* For testing, remove later. */

const zend_function_entry hello_functions[] = { PHP_FE(confirm_hello_compiled, NULL) /* For testing, remove later. */ PHP_FE PHP_FE_END /* Must be the last line in hello_functions[] */};

/* Every user visible function must have an entry in
my_module_functions[].

  PHP_EXTENSION(my_module, $ext_shared)

}

    RETURN_LONG(result);}保存退出,编译并安装:

dnl PHP_ARG_WITH(my_module, for my_module support,

# echo /usr/local/lib > /etc/ld.so.conf.d/local.conf       // 
把库地址写入到配置文件中

 * hellotest.c

一,搭建php环境
下载php 5.2.6 源码 并解压
编译安装,搭建php环境
二,创建扩展项目
进入源码目录
cd php5.2.6/ext/
./ext_skel –extname=my_ext
创建名字为my_ext的项目,最终会生成my_ext.so
三,更改配置和程序
$ vi ext/my_ext/config.m4
根据你自己的选择将
dnl PHP_ARG_WITH(my_ext, for my_ext support,
dnl Make sure that the comment is aligned:
dnl [ –with-my_ext Include my_ext support])
修改成
PHP_ARG_WITH(my_ext, for my_ext support,
Make sure that the comment is aligned:
[ –with-my_ext Include my_ext support])
或者将
dnl PHP_ARG_ENABLE(my_ext, whether to enable my_ext support,
dnl Make sure that the comment is aligned:
dnl [ –enable-my_ext Enable my_ext support])
修改成
PHP_ARG_ENABLE(my_ext, whether to enable my_ext support,
Make sure that the comment is aligned:
[ –enable-my_ext Enable my_ext support])
$ vi ext/my_ext/php_my_ext.h

PHP_FUNCTION(confirm_my_ext_compiled); /* For testing, remove
later. */
更改为
PHP_FUNCTION(say_hello);
$ vi ext/my_ext/my_ext.c

zend_function_entry php5cpp_functions[] = {
PHP_FE(confirm_my_ext_compiled, NULL) /* For testing, remove later.
*/
{NULL, NULL, NULL} /* Must be the last line in php5cpp_functions[]
*/
};
更改为
zend_function_entry php5cpp_functions[] = {
PHP_FE(say_hello, NULL)
{NULL, NULL, NULL} /* Must be the last line in php5cpp_functions[]
*/
};
在最后添加:
PHP_FUNCTION(say_hello)
{
zend_printf(“hello worldn”);
}
四,编译
$ cd my_ext
$ /usr/local/php/bin/phpize
ps: 如果出现:Cannot find
autoconf.……的错误信息,则需要安装 autoconf (安装过程略)
$ ./configure –with-php-config=/usr/local/php/bin/php-config
$ make
这时会编译出 my_ext/modules/my_ext.so
五,配置php.ini
将my_ext.so放入/usr/local/php/ext/目录
$ vi php.ini

PHP_FUNCTION(hello_add);

To use your new extension, you will have to execute the following steps:

Fi

# cp libhello.so /usr/local/lib      // 把生成的链接库放到指定的地址

{

  1. 打开 hello.c,在 PHP_FE(confirm_hello_compiled, NULL)
    下方加入以下内容。

PHP_FUNCTION(hello_add)

然后我们就可以在这个目录下使用上面的命令了
/usr/local/php/bin/phpize
执行以后会看到下面的
[root@ns jinzhesheng_module]# /usr/local/php/bin/phpize
Configuring for:
PHP Api Version:         20020918
Zend Module Api No:      20020429
Zend Extension Api No:   20050606
[root@ns jinzhesheng_module]#
然后执行./configure –enable-jinzhesheng_module
–with-apxs=/usr/local/apache/bin/apxs
–with-php-config=/usr/local/php/bin/php-config
我们在安装以后的php的bin目录下的可以找到这个文件的
php-config 和phpize
这一步骤一定要注意你的apache的apxs放在哪里了
然后执行make
你会看到出现错误了你重新定义了函数我们前面的
这个你在回头改一下这个文件把原来的函数删除掉在生成的文件里面会有同样的函数
你在加入你的代码
就可以通过了
这个时候会在当前的目录下生成一个目录叫modules他的下面就放着你要的
jinzhesheng_module.so文件
cp modules/jinzhesheng_module.so /usr/local/php/ext/
这里需要你先设置你的php的扩展目录的在
在php.ini里面
通过extension_dir
最后一不是你在php.ini文件中打开这个扩展
extension=jinzhesheng_module.so
然后
重新起动apache
用phpinfo来察看一下ok了

修改成

?>

保存文件退出

dnl [  –enable-my_module           Enable my_module support])

{

int hello_add(int a, int b)

luther@gliethttp:~$ sudo service apache2 reload    然后在 /var/www/html
下建立一个 hello.php 文件,内容如下:

修改添加如下:
extension_dir = ‘/usr/local/php/ext/’
extension=my_ext.so
六,测试
$ vi test.php
<?php
say_hello();
?>
$ /usr/local/php/bin/php test.php
hello world.
则大功告成

luther@gliethttp:~$ sudo vim /etc/php5/apache2/php.ini
enable_dl = Off
extension=hello.so
luther@gliethttp:~$ sudo service apache2 restart

# /sbin/ldconfig                // 用此命令,使刚才写的配置文件生效

?>,

$ cd php-5.2.3/ext

int main()

dnl If your extension references something external, use with:

  *   gcc -shared -o libhello.so hello.o

根据你自己的选择将

PHP_FUNCTION(say_hello)

{

PHP_ARG_WITH(my_module, for my_module support,

dnl [  –enable-my_module           Enable my_module support])

    result = hello_add(a, b);

[  –enable-my_module           Enable my_module support])
我这里用了后者
然后保存退出
然后在编辑
Vi my_module.c
将文件其中的下列代码进行修改

*/

    dl(“hello.so”);

  1. 然后通过下面的命令用ext_skel脚本建立一个名为 hello 的模块:

dnl Make sure that the comment is aligned:

<?php

        zend_printf(“hello worldn”);

第一步. 生成需要调用的so文件

在文件的最后添加下列代码

$ ./hellotest           // 运行测试程序

下面我来讲讲如何作一个php的扩展
首先要有一个搭建好的php环境
我把php的安装在了/usr/local/php当然也通过
php的一个配置php.ini的路径但是要注意了
用这种方法安装的php扩展不能实现
我们在php安装以后的/usr/local/php/bin目录
找到这个文件phpize稍后我们将用到他
他就是个shell脚本你可以用vi phpize来查看他的内容
但是你要注意了这个脚本不是在哪里都可以应用的
[root@ns root]# phpize
Cannot find config.m4.
Make sure that you run ‘/usr/local/bin/phpize’ in the top level source
directory of the module

{

  1. 打开 php_hello.h,在 PHP_FUNCTION(confirm_hello_compiled);
    之下加入函数声明:

dnl config.m4 for extension my_module

$ cd hello

#include

[root@ns root]# phpize
Cannot find config.m4.
Make sure that you run ‘/usr/local/bin/phpize’ in the top level source
directory of the module
你会看到这两种结果实际上你查看了这个脚本
很轻松的就会发现是怎么来处理的
你的模扩展的时候最好
放在/usr/local/src/php-4.3.5/ext下
来执行他你在这里也可以这样/usr/local/php/bin/phpize来执行也可以
phpize来执行

*/

    long int result;

  dnl If you will not be testing anything external, like existence of

*   gcc -o hellotest -lhello hellotest.c

 * To compile, use following commands:

1.  首先做一个简单的so文件:

然后我们要修改文件顺序是
configue.m4
jinzhesheng_module.c
php_jinzhesheng_module.h

使用文本编辑器打开config.m4文件,文件内容大致如下:

    然后在 hello.c 的最末尾书写hello_add函数的内容: 

如果要编译成可动态加载的 php_hello.so,方法要更为简单。

     但是该功能不太适合调试,因为每次修改hello.so中代码的话,都需要让service
apacherestart重启才能让php5内核再次加载新的hello.so扩展.可以这样定义hello.so的实现,这样每次执行.php网页,都会在/var/www/下建立一个文件夹,所以php扩展实现了

[注意,这种方式只适合hello.so库内所有功能代码已经全部调试ok,如果还处在调试期间,那么需要采用上面的dl强制加载的方式]

};

$ ./ext_skel –extname=hello

/**

dnl PHP_ARG_WITH(my_module, for my_module support,

    echo hello_add(3, 4);

    long int a, b;

Make sure that the comment is aligned:

16:  PHP_ARG_ENABLE(hello, whether to enable hello support,

  1. 然后执行 phpize 程序,生成configure脚本:

dnl Make sure that the comment is aligned:

或者将

dnl without editing.

 首先编辑 config.m4 文件,去掉第16行和第18行的注释(注释符号为 dnl 。)

dnl Remove where necessary. This file will not work

    PHP_FE(confirm_hello_compiled,  NULL)       /* For testing,
remove later. */

$ gcc -shared -o libhello.so hello.o                     //
-shared:是指明生成动态链接库

 该程序在ubuntu的php5-dev包中

$ phpize

    }

18:  [  –enable-hello           Enable hello support])

$ make LDFLAGS=-lhello

dnl [  –with-my_module             Include my_module support])

Make sure that the comment is aligned:

    {NULL, NULL, NULL}  /* Must be the last line in
hello_functions[] */};

第二步. 制作PHP模块(外部模块)

dnl don’t forget to callPHP_EXTENSION(my_module)

zend_function_entry hello_functions[] = {

我们在/usr/local/src/php-4.3.5/ext下找到这个工具
来建立一个php扩展的一个框架
[root@ns ext]#cd /usr/local/src/php-4.3.5/ext/
[root@ns ext]# ./ext_skel –extname=jinzhesheng_module
Creating directory jinzhesheng_module
Creating basic files: config.m4 .cvsignore
jinzhesheng_module.cphp_jinzhesheng_module.h CREDITS EXPERIMENTAL
tests/001.phptjinzhesheng_module.php [done].

luther@gliethttp:~$ sudo vim /etc/php5/apache2/php.ini;

dnl $Id$d

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “ll”, &a,
&b) == FAILURE) {

dnl PHP_ARG_ENABLE(my_module, whether to enable my_module support,

}

  dnl headers, libraries or functions in them, just uncomment the

$ sudo make install

请确保你已安装 PHP及APACHE服务器。

*/

/** * hello.c

[  –with-my_module             Include my_module support])

发表评论

电子邮件地址不会被公开。 必填项已用*标注