将cpp改为cpp+cu_使用C ++和PHP-CPP开发PHP扩展:高级

将cpp改为cpp+cu

In my earlier articles, I have introduced the PHP-CPP lib to create an extension for PHP using C++ (first article and second article). In the latter, I demonstrated a bit of the OO side of writing a PHP extension with a Complex class doing complex number manipulations.

在我以前的文章中,我介绍了PHP-CPP库以使用C ++为PHP创建扩展( 第一篇第二篇文章 )。 在后者中,我演示了用Complex类进行复杂数字操作编写PHP扩展的面向对象方面。

alt

That introduction is not complete as the main focus of that article is more on the demonstration of the OO capability of PHP-CPP, not on the OO implementation details.

该介绍并不完整,因为该文章的主要重点更多地是在演示PHP-CPP的OO功能,而不是OO实现细节。

In this article, we will further drill down the Complex lib development, adding more member functions, and addressing some advanced topics in writing a PHP extension with OO features using PHP-CPP:

在本文中,我们将进一步深入研究Complex lib的开发,添加更多的成员函数,并通过使用PHP-CPP编写具有OO功能PHP扩展解决一些高级主题:

  • Returning this pointer;

    返回this指针;

  • Returning a Complex object pointer, i.e., a Complex *;

    返回Complex对象指针,即Complex *

  • Exposing the __toString magic method;

    公开__toString魔术方法;

  • Chaining member function calls;

    链接成员函数调用;
  • Throwing an exception and handling it in PHP

    引发异常并在PHP中进行处理

The finished Complex lib source, as well as a test PHP script is located in this Github repo.

完整的Complex lib源代码以及测试PHP脚本位于此Github存储库中

Let’s get started.

让我们开始吧。

准备工作 (Preparations)

The entire process of preparing your environment is explained in the first post.

第一篇文章中介绍了准备环境的整个过程。

在C ++中返回this指针 (Returning this pointer in C++)

As described in the second post, we are using member functions to perform various mathematical operations on complex numbers. In this demo, we will implement four of such functions: add, sub, mul and div. I will explain the first three first. The div function involves exception handling and will be discussed later.

第二篇文章所述 ,我们正在使用成员函数对复数执行各种数学运算。 在此演示中,我们将实现四个这样的功能: addsubmuldiv 。 我将首先解释前三个。 div函数涉及异常处理,将在后面讨论。

Let’s take a look a the mul function (for multiplication). add and sub functions are more or less the same.

让我们看一下mul函数(用于乘法)。 addsub函数大致相同。

Php::Value add(Php::Parameters &params) {
        Php::Value t = params[0];
        Complex *a = (Complex *) t.implementation();

        r += (double) a->getReal();
        i += (double) a->getImage();

        return this;
    }

NOTE: In this article, I will not cover some previously discussed basic topics, like modifying the Makefile and ini file, registering the member functions, class and namespace, etc. Please refer to the previous parts for those bits.

注意:在本文中,我不会涵盖一些先前讨论的基本主题,例如修改Makefile和ini文件,注册成员函数,类和名称空间等。有关这些位,请参阅前面的部分。

Returing a this pointer from C++ back to PHP is straightforward. Inside this C++ function, this pointer (as a Complex * type) can be returned back to PHP as a Php::Value type. The conversion won’t lose any object information. It does not require an explicit type conversion either.

this指针从C ++转换回PHP很简单。 在此C ++函数内部, this指针(作为Complex *类型)可以作为Php :: Value类型返回给PHP。 转换不会丢失任何对象信息。 它也不需要显式类型转换。

返回Complex对象指针 (Returning a Complex object pointer)

Returning this means, most of the time, that the object itself has been changed. But in some cases, we may want to return a new object and keep the “current” object (the calling object) unchanged.

在大多数情况下,返回this意味着对象本身已更改。 但是在某些情况下,我们可能想返回一个新对象,并保持“当前”对象(调用对象)不变。

In our Complex class, we have one such function that returns the conjugated number of a given complex number (a+bi becomes a-bi).

在我们的Complex类中,我们有一个这样的函数,它返回给定复数的共轭数( a+bi变为a-bi )。

Php::Value conjugate() {
        Complex *t = new Complex();

        t->r = r;
        t->i = -i;

        return Php::Object("tr\\Complex", t);
    }

The key point here is that we will have to use Php::Object to explicitly convert our Complex * object into a Php::Object, thus the class information can be properly retained and kept accessible when that object is parsed by a PHP script later.

这里的关键点是,我们将必须使用Php::Object显式地将Complex *对象转换为Php::Object ,这样类信息就可以正确保留并在以后由PHP脚本解析该对象时保持可访问性。 。

The first parameter of this function is the class type, in this case tr\\Complex. I use this name as I have wrapped this class (“Complex“) into a separate namespace (“tr“).

该函数的第一个参数是类类型,在这种情况下为tr\\Complex 。 我将这个类(“ Complex ”)包装到一个单独的命名空间(“ tr ”)中时使用该名称。

The second parameter is the object to be passed back.

第二个参数是要传递回的对象。

Returning a new class instance is a bit trickier than just returning a this pointer but still manageable, as long as you have read through the documentation and found the right section. For some more examples of use, you may want to read this part in PHP-CPP’s official documentation.

只要您已经阅读了文档并找到了正确的部分,返回一个新的类实例就比返回this指针要棘手,但是仍然可以管理。 有关更多使用示例,您可能需要阅读PHP-CPP官方文档中的这一部分

公开__toString魔术方法 (Exposing the __toString magical method)

In our class, there is a __toString function that prints a complex number in a more readable way like: 1+2i. In my previous article, this function is not exposed (or “registered” in PHP-CPP terms) but still can be called from within PHP. But to make this function callable on the Complex object after we apply some math operations like “echo $a->add($b)->sub($c)“, we need to explicitly register it in our compiled extension:

在我们的课程中,有一个__toString函数以更易读的方式打印一个复数,例如: 1+2i 。 在我以前的文章中,此函数未公开(或用PHP-CPP术语“注册”),但仍可以从PHP内调用。 但是,要在应用诸如“ echo $a->add($b)->sub($c) ”之类的一些数学运算之后使此函数在Complex对象上可调用,我们需要在编译后的扩展中显式注册它:

complex.method("__toString", &Complex::__toString);

The reason we have to do so is discussed in detail in the issue submitted to PHP-CPP repository as Issue #150.

在提交给PHP-CPP存储库的问题中,第150期中详细讨论了我们这样做的原因。

链接成员函数调用 (Chaining member function calls)

One thing that must be implemented in this class is the ability to chain member functions so that we can do the calculation like: $a->add($b)->sub($c). The result should still be able to call its member functions.

在此类中必须实现的一件事是链接成员函数的能力,以便我们可以进行如下计算: $a->add($b)->sub($c) 。 结果仍然应该能够调用其成员函数。

This is done by the approach described above, i.e., returning a this pointer back to PHP. However, older PHP-CPP lib has a bug on dereferencing the object and will create a “Segmentation Fault” if the method calls are chained.

这是通过上述方法完成的,即将this指针返回给PHP。 但是,较旧PHP-CPP库在解除引用对象方面存在错误,如果方法调用链接在一起,则会创建“分段错误”。

An issue (#151) has been filed and a commit is submitted with the patch on PHP-CPP source. If you are using an older version of PHP-CPP lib to compile the PHP-CPP lib and your own lib, please update the PHP source and re-compile and re-install the PHP-CPP lib and your lib.

已提交问题( #151 ),并与PHP-CPP源上的修补程序一起提交了提交 。 如果您使用旧版本PHP-CPP库来编译PHP-CPP库和您自己的库,请更新PHP源代码并重新编译并重新安装PHP-CPP库和您的库。

As the commit summary explains:

正如提交摘要所解释的:

fix issue #151, chaining method calls was not working as it should be…
…cause the per-object refcount was not updated correctly, which caused an object to be destructed even when it already was assigned to a different variable.

I am glad that my work on my own project can help the lib I use become better. [Ed: Well done!]

我很高兴自己在自己的项目上所做的工作可以帮助我使用的lib变得更好。 [Ed:干得好!]

PHP中的异常抛出和处理 (Exception throwing and handling in PHP)

There are two more functions in our Complex class that will probably throw an exception back to PHP to handle: div and phi. The former does a division operation and the latter returns the angle of the complex number as in its alternative representation, the polarized notation (r, θ).

我们的Complex类中还有两个函数,它们可能会将异常抛出给PHP处理: divphi 。 前者执行除法运算,而后者返回复数的角度,如其替代表示中的极化符号(r, θ)

Both operations might fail if a complex number is passed as the parameter (or caller) but its real part and image part are 0. For those two operations, we need to have exception handling. Remember, we are to throw an exception in our C++ code and it is the PHP script that will catch the exception and do the necessary handling:

如果将复数作为参数(或调用方)传递,但其实部和映像部均为0,则这两个操作都可能会失败。对于这两个操作,我们需要进行异常处理。 请记住,我们要在我们的C ++代码中引发异常,而PHP脚本将捕获异常并进行必要的处理:

Php::Value div(Php::Parameters &params) {
        Php::Value t = params[0];
        Complex *b = (Complex*) t.implementation();

        double t1 = b->mod() * b->mod();

        if (t1 < EPS) //EPS is a predefined double value which is very small, say 1E-12
            throw Php::Exception("Division by zero");

        double tr = r * (double) (b->getReal()) + i * (double) (b->getImage());
        double ti = i * (double) (b->getReal()) - r * (double) (b->getImage());

        r = tr / t1;
        i = ti / t1;

        return this;
    }

and in the PHP script, we catch this exception like this:

在PHP脚本中,我们捕获了如下异常:

$a=new tr\Complex(1,2);
$c=new tr\Complex(); //$c is actuall 0+0i

try
{
    $res=$a->div($c);
}
catch(Exception $e)
{
    echo "Caught exception: ".$e->getMessage()."\n";
}
}

The above code segment will display a line of text as below:

上面的代码段将显示一行文本,如下所示:

Caught exception: Division by zero

Easy, right? A C++ exception constructed inside our extension is passed back to PHP and caught properly. Furthermore, we can manipulate the exception as if it were a native PHP exception thrown by some other PHP code!

容易吧? 在我们的扩展中构造的C ++异常被传递回PHP并被正确捕获。 此外,我们可以像处理其他PHP代码引发的本机PHP异常一样处理该异常!

测试所有功能 (Test all the functions)

Finally, we can compile and install the complex.so extension for our PHP installation via make && sudo make install. If everything goes smoothly, we can verify the installation of our extension by issuing this command in the terminal:

最后,我们可以通过make && sudo make install编译并安装PHP安装的complex.so扩展。 如果一切顺利,我们可以通过在终端中发出以下命令来验证扩展程序的安装:

php -i | grep complex

The terminal should display a line saying “/etc/php5/cli/conf.d/complex.ini” and we can be sure that our extension is installed and ready to be called by any PHP scripts.

终端应显示一行“ /etc/php5/cli/conf.d/complex.ini ”,我们可以确定已经安装了扩展程序,并且可以被任何PHP脚本调用。

NOTE: If we examine the Makefile for this extension, we will see that we are installing this PHP extension into its CLI environment. If we want to install this extension so that it will be loaded by Apache, we change the below line:

注意:如果我们检查此扩展的Makefile ,将会看到我们正在将该PHP扩展安装到其CLI环境中。 如果要安装此扩展,以便它将由Apache加载,请更改以下行:

# Below is for installation to CLI
#INI_DIR = /etc/php5/cli/conf.d
# Below is for installation to Apache
INI_DIR  = /etc/php5/apache2/conf.d

The testing PHP script for this extension is excerpted below with some comments:

下面摘录了此扩展的测试PHP脚本,并提供了一些注释:

//Testing the mod function
//Displays 5
$c=new tr\Complex(-3,-4);
echo "Mod of $c is: ".$c->mod()."\n";
...
//Testing a string representation of a complex number
//Displays: -4-3i
$e=new tr\Complex(-4,-3);
echo ((string)$e."\n");
...
//Chain the member function calls
$a=new tr\Complex(1,1);
$b=new tr\Complex(1,2);
...
echo ($a->add($b)->sub($c)->add($d))."\n";
...
//Exception handling
$a=new tr\Complex(1,2);
$c=new tr\Complex();

try
{
    $res=$a->div($c);
}
catch(Exception $e)
{
    echo "Caught exception: ".$e->getMessage()."\n";
}

All the test scripts should run correctly and the exceptions are caught properly.

所有测试脚本均应正确运行,并且可以正确捕获异常。

结论 (Conclusion)

This concludes my 3-article series on this powerful lib to build a PHP extension with C++. We covered the basics, the OO side and some advanced topics in OO programming. We also helped PHP-CPP improve a bit.

这是我关于此功能强大的lib的3个系列的文章的结尾,以使用C ++构建PHP扩展。 我们介绍了OO编程的基础知识,面向对象方面和一些高级主题。 我们还帮助PHP-CPP进行了一些改进。

What else can we do with PHP-CPP? I will quote a few lines from the email correspondences that I received from Emiel Bruijntjes (co-author of PHP-CPP):

PHP-CPP还可以做什么? 我将引用我从Emiel Bruijntjes(PHP-CPP的合著者)收到的电子邮件中的几行内容:

The PHP-CPP library is ideal to use if you’re working on a project, and you have one or more of the following requirements: – You are working on a piece of software / data structure / algorithm, and you want to ensure that in the future your software can be used in non-PHP projects as well. – You want to make use of tools or libraries that have not yet been made available as PHP extension. – You want the better performance of C/C++ code (compared to PHP), but you also want to build structured, object-oriented code, that is easy to understand and easy to maintain for other developers / colleagues.

如果您正在处理项目,并且具有以下一个或多个要求,则PHP-CPP库是理想的选择:–您正在处理一个软件/数据结构/算法,并且要确保将来,您的软件也可以在非PHP项目中使用。 –您要使用尚未作为PHP扩展提供的工具或库。 –您希望C / C ++代码具有更好的性能(与PHP相比),但是您还希望构建结构化的,面向对象的代码,该代码对于其他开发人员/同事而言易于理解和维护。

The possibilities are enormous: a framework (like Phalcon), a template language (like Smarty or Twig), etc.

可能性是巨大的:框架(如Phalcon),模板语言(如Smarty或Twig)等。

Please leave your comments and views, and let us know what you have done with this lib!

请留下您的评论和意见,并让我们知道您对这个库所做的一切!

翻译自: https://www.sitepoint.com/developing-php-extensions-c-php-cpp-advanced/

将cpp改为cpp+cu

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值