[教学] 用 PHP-CPP 写 PHP extension (2)

楼主: Neisseria (Neisseria)   2016-12-07 11:39:39
延续上一篇,我们会展示另一个范例
在这个范例中,我们会建立 PHP 物件 (object),并呼叫其方法 (method)
如果想直接研究程式码,可到这个 repo
https://github.com/cwchentw/matrix-php-extension-demo
首先,实作 matrix 这个 toy library
在这里,我们也是用 Rust 实作。同样地,也要手动撰写 header
#ifndef _MATRIX_H_
#define _MATRIX_H_
#ifdef __cplusplus
extern "C" {
#endif
void* matrix_new(size_t, size_t);
double matrix_get_at(void*, size_t, size_t);
void matrix_set_at(void*, double, size_t, size_t);
void matrix_free(void*);
#ifdef __cplusplus
}
#endif
#endif // _MATRIX_H_
为了简化范例,我们没有实作 matrix 的操作
仅建立 getter/setter,请板友包涵
同样要下载 EmptyExtension 这个专案骨架,请板友自行完成。
接下来,实作 C++ 程式码
#include <phpcpp.h>
#include "matrix.h"
class Matrix : public Php::Base
{
public:
void* m; // Our matrix struct
Matrix() = default; // Dummy constructor
~Matrix();
void __construct(Php::Parameters&); // PHP constructor
Php::Value get_at(Php::Parameters&);
void set_at(Php::Parameters&);
};
Matrix::~Matrix()
{
matrix_free(this->m);
}
void Matrix::__construct(Php::Parameters &params)
{
this->m = matrix_new((int32_t)params[0], (int32_t)params[1]);
}
Php::Value Matrix::get_at(Php::Parameters &params)
{
return matrix_get_at(this->m, (int32_t)params[0], (int32_t)params[1]);
}
void Matrix::set_at(Php::Parameters &params)
{
matrix_set_at(this->m, (double)params[0],
(int32_t)params[1], (int32_t)params[2]);
}
要特别注意 constructor 的部分。由于 PHP 不能直接使用 C++ 的 constructor
要额外建立一个 __construct 方法,并在里面实做 constructor 的程式码
另外建立一个 dummy constructor 给 C++ 用
在我们这个专案中,m 是实际从 Rust 输出的 struct。
一般常规是将其设为 private,这里将其设为 public
因为在 PHP 层级,不会动到这个 struct
将其设为 public 有利于物件操作 e.g. matrix 相乘
同样地,将其输出到 PHP
extern "C" {
PHPCPP_EXPORT void *get_module()
{
static Php::Extension extension("matrix", "1.0");
Php::Class<Matrix> matrix("Matrix");
matrix.method<&Matrix::__construct>("__construct", {
Php::ByVal("row", Php::Type::Numeric),
Php::ByVal("col", Php::Type::Numeric)
});
matrix.method<&Matrix::get_at>("get_at", {
Php::ByVal("row", Php::Type::Numeric),
Php::ByVal("col", Php::Type::Numeric)
});
matrix.method<&Matrix::set_at>("set_at", {
Php::ByVal("value", Php::Type::Float),
Php::ByVal("row", Php::Type::Numeric),
Php::ByVal("col", Php::Type::Numeric)
});
extension.add(std::move(matrix));
return extension;
}
}
最后,撰写简单的 PHP 程式测试此 PHP extension
<?php
// main.php
$m = new Matrix(3, 3);
echo $m->get_at(1, 1), "\n";
$m->set_at(99, 1, 1);
echo $m->get_at(1, 1), "\n";
若不想安装 extension,也可从命令列呼叫
$ php -dextension=`pwd`/matrix.so main.php
这个范例到此大致上结束了
使用 PHP-CPP,仍然需要基本的 C++ 相关知识
而且,PHP-CPP 官网说明略为简略,有时还是得去翻 PHP-CPP 的 header
如果使用 Zephir,可以用更接近 PHP 的语法来撰写
那个方案较好,板友可再自行评估
分享给有需要的板友

Links booklink

Contact Us: admin [ a t ] ucptt.com